1

我正在开发一个带有两个线程的 Java/Seam/Hibernate/Glassfish 应用程序:

  • 线程 #1发送各种消息并将摘要信息写入 MySQL 数据库。
  • 线程 #2定期轮询数据库(由 a 调用ScheduledExecutorService)并作用于每条消息的当前“状态”。

遇到了一个集成测试问题:Thread #2等待Thread #1添加新行的时间似乎并不重要,它只是在测试期间没有添加,所以没有进行预期的调用. 果然,在测试失败后会弹出一个新行 - 但为时已晚。不确定这是否可能是一个设计问题 -线程 #2当前使用Lifecycle.beginCall()...Lifecycle.endCall(). 所以我的理解(这可能是错误的)可能是由于两个线程有​​两个单独的 Hibernate 会话 - 所以一个阅读不知道来自一个写作的最新信息?

可能有不同的方法来解决这个问题,但我目前的想法是我不能在我调用save()/flush()甚至手动提交事务时强制 Hibernate 立即将记录添加到表中吗?这些都没有运气 - 让我想知道是否在幕后使用了某种托管事务。感谢您的任何建议...

有关信息,这是添加记录的代码的要点:

// Obtain Hibernate session
Session session = (Session) Component.getInstance("hibernateSession");

// Create request
Request newRequest = new Request();
// newRequest.set<blah>();

// Save the new request to the database
session.save(newRequest);

// Have tried session.flush(), transaction.commit() etc. here.
// Nothing seems to put the record into the database straight away.

不确定这是否相关,但这里是 Hibernate 配置:

<property name="transaction.flush_before_completion">true</property>
<property name="connection.release_mode">after_statement</property>
<property name="transaction.manager_lookup_class">org.hibernate.transaction.SunONETransactionManagerLookup</property>
<property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
<property name="current_session_context_class">jta</property>

(由于这是客户拥有的现有应用程序,我无权更改 Hibernate 配置。)

4

2 回答 2

1

你的猜测不错。

您正在使用JTATransactionFactory,因此事务由 JTA 划分(即由容器划分)。

您用来保存的方法Request(这里我假设它是在 EJB 中定义的)需要使用事务注释进行注释:@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW),因此当方法结束时,事务被提交。

于 2013-02-13T12:56:54.523 回答
0

非常感谢@Carlo Pellegrini,他的回答为我指明了正确的方向。从那以后,我遇到了这个答案,并在 save() 操作后尝试了以下代码:

// Commit Seam-managed transaction (if there is one)
UserTransaction userTransaction = (UserTransaction) Component.getInstance("org.jboss.seam.transaction.transaction");
if (userTransaction.isActive()) {
    userTransaction.commit();
}

好吧,它很好地完成了这项工作,但我不喜欢它 - 似乎有点 hacky!有没有更好的办法?

于 2013-02-13T17:01:31.960 回答