并发执行事务时出现Hibernate异常



我有一个简单的方法:

public void addPerson(Person person) {
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();
em.persist(person);
transaction.commit();
} catch (Exception e) {
log.error("Exception occurred: ",e);
}
}

当从多个线程同时调用此方法时,我会得到以下异常:

Caused by: javax.persistence.PersistenceException: org.hibernate.HibernateException: Flush during cascade is dangerous
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:65)
... 35 more
Caused by: org.hibernate.HibernateException: Flush during cascade is dangerous
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1449)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:511)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3290)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2486)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
... 34 more

如何解决这个问题?

很可能,您的两个线程共享同一个Hibernate会话。Session类的文档中明确提到

实现者是线程安全的并不是有意的。相反,每个线程/事务应该从会话工厂。

因此,对于每个线程,您需要执行以下操作:

SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();

然后开始并提交您的事务,最后记住关闭会话:

session.beginTransaction();
//Do something
session.getTransaction().commit();

最新更新