I suspect this one is embarrassing an I am doing it wrong in a terrible way, but please bear with me.
I have a Spring application with Spring-managed transactions.
It uses EclipseLink JPA.
I have a method which does a findByNativeQuery()
followed by a merge()
. I need this to happen in a real SERIAL transaction isolation level.
I tried adding
@Transactional(isolation=Isolation.SERIALIZABLE)
This doesn't work because org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect#beginTransaction
does not support any transaction isolation level but the default.
So then I tried getting to UnitOfWork internals of ElcipseLink and starting/comitting my own transactions, but then I get an error:
"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 do I do??
I've given a try to this, but I am not completely sure of the solution. I've taken the code from this blog and adapted it for EclipseLink. Here's 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'm seeing the SERIALIZABLE isolation being logged when the transaction is initiated, but this needs to be tested properly to confirm it works.
Support for custom isolation level was added in Spring 4.1.2 to EclipseLinkJpaDialect
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With