Spring Managed Transactions, EclipseLink JPA, Customizable Isolation Level

I suspect this is embarrassing, that I am doing it wrong in a terrible way, but please carry me.

I have a Spring application with Spring-driven transactions. It uses the EclipseLink JPA. I have a method that executes findByNativeQuery() , followed by merge() . I need this to happen at the real level of transaction isolation SERIAL. I tried adding @Transactional(isolation=Isolation.SERIALIZABLE)

This does not work because org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect#beginTransaction does not support transaction isolation level, but by default. So, I tried to connect to UnitOfWork ElcipseLink modules and start / commit my own transactions, but then I get an error message:

 "java.lang.IllegalStateException : Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead 

Which, of course, makes sense ... but what should I do?

+6
source share
3 answers

I tried to do this, but I'm not quite sure about the solution. I took the code for this blog and adapted it for EclipseLink. Here is the code:

 package com.byteslounge.spring.tx.dialect; import java.sql.SQLException; import javax.persistence.EntityManager; import javax.persistence.PersistenceException; import org.eclipse.persistence.sessions.UnitOfWork; import org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionException; public class CustomEclipseLinkJpaDialect extends EclipseLinkJpaDialect { private static final long serialVersionUID = 1L; private boolean lazyDatabaseTransaction = false; @Override public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) { this.lazyDatabaseTransaction = lazyDatabaseTransaction; } @Override public Object beginTransaction(final EntityManager entityManager, final TransactionDefinition definition) throws PersistenceException, SQLException, TransactionException { UnitOfWork uow = (UnitOfWork) getSession(entityManager); uow.getLogin().setTransactionIsolation(definition.getIsolationLevel()); entityManager.getTransaction().begin(); if (!definition.isReadOnly() && !lazyDatabaseTransaction) { uow.beginEarlyTransaction(); } return null; } } 

I can see that SERIALIZABLE isolation is logged at the start of the transaction, but it needs to be checked correctly to confirm that it works.

+6
source

Custom isolation level support was added in Spring 4.1.2 in EclipseLinkJpaDialect

+3
source

You can refer

"To achieve serialization of transaction isolation using EclipseLink, we recommend that you use an isolated client session as follows:

Configure database transaction isolation as serializable. Configuring objects as isolated (see setting cache isolation at the project level or Setting cache isolation at the descriptor level). Use the UnitOfWork method beginTransactionEarly (see Section Working method beginTransactionEarly). If you are concerned only with the recording aspect of a serializable, optimistic locking is enough. "

at http://docs.oracle.com/middleware/1212/toplink/OTLCG/cache.htm or go through http://docs.oracle.com/middleware/1212/toplink/OTLCG/cache.htm if any level insulation meets your requirement

0
source

Source: https://habr.com/ru/post/971023/


All Articles