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

Lai*_*son 8 hibernate ejb transactions java-ee

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

有些文章指出,即使是简单的读取操作,也应始终使用数据库事务.这是一个对我来说很有意义的任意示例: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.

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

Lam*_*bda 2

如果我有一个执行只读操作的 EJB 方法,那么始终将其声明为事务性的(遵循上述 Hibernate 建议的精神)是一个好的做法吗?

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

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

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

因此,如果根据返回的Statistics对象生成报告,则无法保证该报告是基于当时已经可用的所有统计数据T2

同样,根据您尝试实现的要求,这有时是可以接受的,有时则不是。