2013-02-13 83 views
1

我正在开发一个Java /缝/休眠/ GlassFish应用有两个线程:如何强制将新记录立即保存到数据库* *

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

所遇到的集成测试问题:它似乎并不重要多久线程#由线程#1,它只是不添加过程中添加2等待新行测试,所以预期的呼叫是不是。然后果然,测试失败后会出现一个新的行 - 但为时已晚。不知道这是否可能是设计问题 - 线程#2当前使用Lifecycle.beginCall()...Lifecycle.endCall()获取Seam上下文。所以我的理解(这可能是错误的)可能是因为两个线程有​​两个单独的Hibernate会话 - 所以一个阅读不知道来自一个写作的最新信息?

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

有关的信息,这里的代码,增加了一个创纪录的要点:

// 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配置。)

回答

1

您的猜测很好。

您使用的是JTATransactionFactory,因此交易是由JTA(即容器)划定的。

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

+0

嗯,这看起来不错,可能接近标记,但该方法不在EJB中。我试过Seam的@Transactional属性,但这没有什么区别......有什么建议吗? – 2013-02-13 15:17:55

+0

(我可能应该提到它是Seam v2.2.1)。 – 2013-02-13 15:52:45

0

非常感谢@Carlo Pellegrini,他的回答指出我的方向是正确的。我因为遇到this answer和保存()操作之后,尝试下面的代码:

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

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

相关问题