Hibernate,spring,JPS和隔离 – 不支持自定义隔离

我一直在尝试这个:

@Transactional(isolation=Isolation.SERIALIZABLE, rollbackFor={Exception.class}, propagation=Propagation.REQUIRES_NEW) 

关于我的服务方法,但spring抱怨说:

 Standard JPA does not support custom isolation levels - use a special JpaDialect 

我该如何解决这个问题?

这个实现不是清理工作的原因,我已经实现了类似的解决方案,但也考虑了清理。 该解决方案可以在这里找到: http : //shahzad-mughal.blogspot.com/2012/04/spring-jpa-hibernate-support-for-custom.html

JPA不支持自定义隔离级别。 您可以扩展HibernateJpaDialect类并覆盖与连接相关的方法,以便您可以在Connection上设置自定义隔离级别

这是我写的东西,但还没有测试过:

 public class HibernateExtendedJpaDialect extends HibernateJpaDialect { @Override public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) throws PersistenceException, SQLException, TransactionException { Session session = (Session) entityManager.getDelegate(); DataSourceUtils.prepareConnectionForTransaction(session.connection(), definition); entityManager.getTransaction().begin(); return prepareTransaction(entityManager, definition.isReadOnly(), definition.getName()); } } 

并将此定义为EntityManagerFactory的属性:

    

借鉴Bozho的答案并考虑其上的评论,以下似乎是一个完整的(Hibernate 4兼容)解决方案,解决了重置连接的需要。 最好我可以告诉,spring层将保证调用cleanupTransaction方法,但如果实际上没有保证,可能需要重新考虑这可能是由于permGen内存泄漏的可能性以及对连接对象的post请求副作用。

 public class HibernateExtendedJpaDialect extends HibernateJpaDialect { ThreadLocal connectionThreadLocal = new ThreadLocal<>(); ThreadLocal originalIsolation = new ThreadLocal<>(); @Override public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) throws PersistenceException, SQLException, TransactionException { boolean readOnly = definition.isReadOnly(); Connection connection = this.getJdbcConnection(entityManager, readOnly).getConnection(); connectionThreadLocal.set(connection); originalIsolation.set(DataSourceUtils .prepareConnectionForTransaction(connection, definition)); entityManager.getTransaction().begin(); return prepareTransaction(entityManager, readOnly, definition.getName()); } /* We just have to trust that spring won't forget to call us. If they forget, we get a thread-local/classloader memory leak and messed up isolation levels. The finally blocks on line 805 and 876 of AbstractPlatformTransactionManager (Spring 3.2.3) seem to ensure this, though there is a bit of logic between there and the actual call to this method. */ @Override public void cleanupTransaction(Object transactionData) { try { super.cleanupTransaction(transactionData); DataSourceUtils.resetConnectionAfterTransaction( connectionThreadLocal.get(), originalIsolation.get()); } finally { connectionThreadLocal.remove(); originalIsolation.remove(); } } } 

@Shahzad Mughal我给你留了两点;-)你的答案应该被接受为正确答案。 接受的答案将产生以下问题随机错过领先的开发人员认为有错误的mysql驱动程序,例如:

WARN [org.hibernate.util.JDBCExceptionReporter] – SQL错误:0,SQLState:S1009错误[org.hibernate.util.JDBCExceptionReporter] – 连接是只读的。 不允许导致数据修改的查询

您可以在http://thinkinginsoftware.blogspot.com/2013/10/connection-is-read-only-queries-leading.html上阅读有关此问题的更多信息。

指定JpaTransactionManager时是否指定了JPADialect? 默认情况下,我认为它使用DefaultJpaDialect ,你需要HibernateJpaDialect 。

您也可以使用“IsolationLevelDataSourceAdapter”包装“datasource”bean,只需执行以下操作:

     

其中“_dataSource”是对实际数据源的引用。