拥有非事务性EJB“读取”方法是否是一种好的做法?

时间:2011-08-19 16:06:56

标签: hibernate java-ee transactions ejb

这是一个非常谦虚的问题。

有些文章指出,即使是简单的读取操作,也应始终使用数据库事务。这是一个对我来说很有意义的任意示例:http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions Hibernate文档本身也说:

  

始终使用明确的事务边界,即使是只读操作。

好的,看起来很清楚。这一直是我的假设,即。因为在所有情况下都会在数据库级隐式地应用事务,所以最好总是明确地声明它们。

然后我读了这样的其他文章:http://www.ibm.com/developerworks/java/library/j-ts1/index.html#never(注意标注)。这篇文章部分地说:

  

永远不要说永远

     

在某些时候,您可能希望为数据库读取操作启动事务,例如,在隔离读取操作以确保一致性或为读取操作设置特定事务隔离级别时。但是,这些情况在业务应用程序中很少见,除非您遇到这种情况,否则应避免为数据库读取操作启动事务,因为它们是不必要的,并且可能导致数据库死锁,性能低下和吞吐量低。

关于死锁和吞吐量低的问题对​​我来说也很有意义。

最低级别的建议冲突。没关系;作为一个不起眼的应用程序开发人员,我可以在这里构建自己的想法,我认为:更喜欢以前的建议,也许看看给定的ORM /数据库组合是否在某些性能关键的情况下没有事务就能获得更好的性能。如果我错了,请纠正我。

现在我回到了应用服务器和XA事务的领域。

如果我有一个只执行只读操作的EJB方法,那么总是将它声明为事务性(遵循上面的Hibernate建议的精神)是不错的做法?或者将其标记为@TransactionAttribute(TransactionAttributeType.SUPPORTS)并不是对金属附近的数据库交易策略有多大影响?

我的意思是,EJB(JTA)事务发生在应用程序服务器级别。可能是这种情况(我不知道)当Java EE应用程序服务器与Hibernate交互时,Hibernate将始终强制执行显式数据库级事务,而不管应用程序服务器级事务策略到位。因此,我在这里引用的以Hibernate为重点的文章可能不适用于应用程序服务器级别的JTA事务 - 也许 是将只读方法标记为@TransactionAttribute(TransactionAttribute.SUPPORTS)的良好做法REQUIRED

这里有什么人的想法?所有指针 - 甚至是基本信息 - 都受到欢迎。

2 个答案:

答案 0 :(得分:3)

我认为使用TransactionAttribute.SUPPORTS没有问题,但您必须确定您正在运行的上下文。

你真正说的是:“我不关心脏读”。或幻像读。您返回给用户的数据不能保证处于一致状态,对于很多应用程序来说,这很好。

实际上,我发现作为企业开发人员,我们倾向于过度使用交易。它们有很大的开销。而且,如果读入的数据不会影响写入操作,那么您的业务案例实际上可能容忍显示一些陈旧数据。

简而言之,我认为EJB3 Tx注释都是出于某种目的。如果你理解他们的语义和你的应用程序,你可以做出明智的决定Tx模式更合适。

S,
ALR

答案 1 :(得分:2)

  

如果我有一个只执行只读操作的EJB方法,那就好了   练习总是声明它是交易性的(遵循   上面的Hibernate建议的精神)?

在我看来,这取决于您正在实施的用例的要求。如果允许不可重复的读取和/或幻像读取,则不需要始终在事务内部运行只读方法。对于某些类型的搜索或报告生成任务,这是可以接受的。另一方面考虑这样的情况:

List<Post> posts = findAllPosts();
for (Post p : posts) {
  Statistics s = findStatisticByPostId(p.id);
  doSomethingWithStatistics(s);
}

在这种情况下,一个帖子可能会在时间T1之前返回其统计信息,而另一个帖子可能会在时间T2, where T2 > T1之前返回,因为每次调用findStatisticByPostId都会在自己的交易中运行。并且两个帖子都可以在(T1...T2)期间看到一些统计信息。

因此,如果您根据返回的Statistics对象生成报告,则无法保证报告基于时间T2之前可用的所有统计信息。

再次取决于您尝试实施的要求,这有时是可以接受的,有时也不是。