-
Notifications
You must be signed in to change notification settings - Fork 38.5k
HibernateJpaDialect does not support setting a specific isolation level per transaction [SPR-5012] #9687
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Juergen Hoeller commented This is a known limitation: All current JPA providers make it pretty hard to set a specific isolation level for a native transaction. This is caused by the general JPA assumption that JDBC Connections will always be retrieved on demand, not necessarily held for the lifetime of a transaction... For a native transaction, the provider will have to hold a Connection per transaction eventually, but it may fetch it lazily on first access and it may release it right after transaction commit. This makes it hard to set an isolation level at the JDBC Connection level, and particularly hard to reset the original isolation level before returning the Connection to the pool! In any case, this should be better documented. The InvalidIsolationLevelException message could be more specific as well. I'll revise the doc bits for Spring 2.5.6. Juergen |
Samuel Gaiffe commented Thank you Juergen. I know all of this but I wanted to know if I get the desired isolation level by using this workaround or if it just bypass the isolation level setting ? Samuel |
Juergen Hoeller commented I'm afraid this workaround will just bypass the isolation level setting... Juergen |
Samuel Gaiffe commented I'll make some test to verify it and i'll let you know. Thank you again. Samuel |
Gaetan Pitteloud commented In the case when JPA is used in local mode, which means it is configured with a DataSource, would a JpaDialect implementation that's implemented like the corresponding transaction manager do the job ? More precisely, I use Hibernate as the JPA provider and JPA is local (not JTA); would a JPA Dialect implementation that does exactly what HibernateTransactionManager does in its doBegin(), in addition to HibernateJpaDialect, do the job ? Thanks for the reply. |
Gaetan Pitteloud commented I guess the problem comes in this call : |
Stevo Slavić commented Just to note, IMO this issue is related to #8492, so maybe these could be linked. |
Eugen Paraschiv commented This seems to be a significant limitation with JPA, and one that could potentially be fixed at least when not using JTA transactions. Is there any way to handle that case by improving the HibernateJpaDialect? |
Juergen Hoeller commented Addressed for Hibernate EntityManager 4 in #16559. |
Uh oh!
There was an error while loading. Please reload this page.
Samuel Gaiffe opened SPR-5012 and commented
Hi,
our problem is in unit testing. When we deploy under Weblogic and use the Weblogic transaction manager, everything is ok.
But for unit testing, we use a LocalContainerEntityManagerFactoryBean with a HibernateJpaVendorAdapter injected into a JpaTransactionManager.
When isolation level other than DEFAULT is required for a transaction (setted through annotations), an InvalidIsolationLevelException is thrown.
I have solved this problem by writing a CustomHibernateJpaDialect in which I just delete the throw exception :
<i>
public class CustomHibernateJpaDialect
extends HibernateJpaDialect
{
public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition)
throws PersistenceException, SQLException,
TransactionException
{
entityManager.getTransaction().begin();
return null;
}
public void cleanupTransaction(Object transactionData) {
// This line throws a NullPointerException. Got no time to go deeper but we never change the flush mode so I let it commented
//((SessionTransactionData) transactionData).resetFlushMode();
}
}
</i>
and a CustomHibernateJpaVendorAdapter in which I use my new CustomHibernateJpaDialect :
<i>
public class CustomHibernateJpaVendorAdapter extends AbstractJpaVendorAdapter
{
private final PersistenceProvider persistenceProvider = new HibernatePersistence();
private final JpaDialect jpaDialect = new CustomHibernateJpaDialect();
public PersistenceProvider getPersistenceProvider() {
return this.persistenceProvider;
}
public Map getJpaPropertyMap() {
Properties jpaProperties = new Properties();
}
/**
@param
database the target database@return
the Hibernate database dialect class, or <code>null<code> if none found*/
protected Class determineDatabaseDialectClass(Database database) {
switch (database) {
case DB2: return DB2Dialect.class;
case HSQL: return HSQLDialect.class;
case INFORMIX: return InformixDialect.class;
case MYSQL: return MySQLDialect.class;
case ORACLE: return Oracle9Dialect.class;
case POSTGRESQL: return PostgreSQLDialect.class;
case SQL_SERVER: return SQLServerDialect.class;
case SYBASE: return SybaseDialect.class;
default: return null;
}
}
public Class<? extends EntityManager> getEntityManagerInterface() {
return HibernateEntityManager.class;
}
public JpaDialect getJpaDialect() {
return this.jpaDialect;
}
}
</i>
I can't believe it's all we have to do to make it work correctly but I can go ahead in my unit testing.
Is my isolation level really set (I want SERIALIZABLE) ?
Thank you
Affects: 2.5.2
Issue Links:
6 votes, 11 watchers
The text was updated successfully, but these errors were encountered: