javax.transaction.Transactional 与 org.springframework.transaction.annotation.Transactional

Posted

技术标签:

【中文标题】javax.transaction.Transactional 与 org.springframework.transaction.annotation.Transactional【英文标题】:javax.transaction.Transactional vs org.springframework.transaction.annotation.Transactional 【发布时间】:2014-12-10 19:35:43 【问题描述】:

我不明白注解javax.transaction.Transactionalorg.springframework.transaction.annotation.Transactional 之间的实际区别是什么?

org.springframework.transaction.annotation.Transactionaljavax.transaction.Transactional 的扩展还是它们的含义完全不同?什么时候应该使用它们? Spring @Transactinal 在服务层和 javax 在 DAO?

感谢您的回答。

【问题讨论】:

【参考方案1】:

声明性事务范围

Spring 和 JPA @Transaction 注释都允许您定义给定应用程序事务的范围。

因此,如果使用@Transactional 注释对服务方法进行注释,它将在事务上下文中运行。如果服务方法使用多个DAO或Repositories,所有的读写操作都会在同一个数据库事务中执行。

春天@Transactional

org.springframework.transaction.annotation.Transactional 注解从 Spring 框架的 1.2 版本(大约 2005 年)开始可用,它允许您设置以下事务属性:

isolation:底层数据库隔离级别 noRollbackFornoRollbackForClassName:可以在不触发事务回滚的情况下触发的 Java Exception 类的列表 rollbackForrollbackForClassName:Java Exception 类在抛出时触发事务回滚的列表 propagationPropagation 枚举给出的事务传播类型。例如,如果事务上下文可以被继承(例如,REQUIRED)或者应该创建一个新的事务上下文(例如,REQUIRES_NEW),或者如果不存在事务上下文应该抛出异常(例如,@987654341 @) 或者如果找到当前事务上下文(例如,NOT_SUPPORTED)则应引发异常。 readOnly:当前事务是否应该只读取数据而不应用任何更改。 timeout:在抛出超时异常之前,应该允许事务上下文运行多少秒。 valuetransactionManager:绑定事务上下文时要使用的 Spring TransactionManager bean 的名称。

Java EE @Transactional

javax.transaction.Transactional 注释是由 Java EE 7 规范(大约 2013 年)添加的。因此,Java EE 注释的添加比其 Spring 注释晚了 8 年。

Java EE @Transactional 只定义了 3 个属性:

dontRollbackOn:可以在不触发事务回滚的情况下触发的 Java Exception 类列表 rollbackOn:被抛出时触发事务回滚的 Java Exception 类列表 value:传播策略,由TxType Enum 给出。例如,如果事务上下文可以被继承(例如,REQUIRED)或者应该创建一个新的事务上下文(例如,REQUIRES_NEW),或者如果不存在事务上下文应该抛出异常(例如,@987654359 @) 或者如果找到当前事务上下文(例如,NOT_SUPPORTED)则应引发异常。

选择哪一个?

如果您使用的是 Spring 或 Spring Boot,请使用 Spring @Transactional 注释,因为它允许您配置比 Java EE @Transactional 注释更多的属性。

如果您单独使用 Java EE,并且将应用程序部署在 Java EE 应用服务器上,请使用 Java EE @Transactional 注释。

【讨论】:

Java/Jakarta EE @Transactional 注释是否适用于 private 方法? 很可能不是。事务边界应该在从不同层调用服务时开始,例如 Web 或调度程序。 实际上,我已经在同一个类中有一个委托方法,该方法使用@Transactional 注释。我知道我可以将注解移到这个委托方法上,但是我对此很好奇,我在网上没有找到任何东西。 私有方法不算。 propagation rules 仅计算服务间方法。【参考方案2】:

另一个区别是Spring如何处理@Transactional注解

org.springframework.transaction.annotation.Transactional 总是被考虑在内 javax.transaction.Transactional 仅在存在 EJB3 事务时才考虑在内。 EJB3 事务的存在是通过检查类javax.ejb.TransactionAttribute 在类路径中是否可用(从版本 2.5.3 到 3.2.5)来完成的。 因此,如果只有javax.transaction.Transactional 在您的类路径中而不是javax.ejb.TransactionAttribute,您最终可能会不考虑您的注释。 如果您使用 Hibernate,可能会出现这种情况:hibernate-core (4.3.7.Final) 依赖于 jboss-transaction-api_1.2_spec (1.0.0.Final),它不提供 javax.ejb.TransactionAttribute.

【讨论】:

我认为这不再是 Spring 4.2.0 的问题:javax.transaction.Transactional annotation is also supported as a drop-in replacement to Spring’s own annotation 它并不总是被采用,如果它在私有方法上例如它不会被采用。【参考方案3】:

请小心,(这个问题发生在tomcat中),

如果您的应用程序是 SPRING Web 应用程序并且您正在使用 Spring 的事务处理机制 @org.springframework.transaction.annotation.Transactional,那么不要将它与 javax.transaction.Transactional 混合使用。

在 Spring 应用程序中始终使用 @org.springframework.transaction.annotation.Transactional

否则我们可能会出现这个错误,

org.springframework.orm.jpa.JpaSystemException: commit failed; nested exception is org.hibernate.TransactionException: commit failed

........

Caused by: java.sql.SQLException: Protocol violation: [0]

【讨论】:

注意:这个答案是我的答案的特例【参考方案4】:

几年前,Spring 已经定义了自己的 Transactional 注释,以使 Spring bean 方法具有事务性。

Java EE 7 终于做了同样的事情,现在除了 EJB 方法之外,还允许 CDI bean 方法是事务性的。所以从 Java EE 7 开始,它也定义了自己的 Transactional 注解(显然不能重用 Spring 的注解)。

在 Java EE 7 应用程序中,您将使用 Java EE 注释。

在 Spring 应用程序中,您将使用 Spring 注释。

它们的用途是相同的:通知容器(Java EE 或 Spring)一个方法是事务性的。

【讨论】:

不仅如此:为了统治宇宙,Spring 还添加了对javax.transaction.Transactional 的隐式支持,因此现在人们也可以在 Spring 应用程序中使用它而无需任何额外操作。 IMO,从设计的角度来看,这是一个非常糟糕的决定,因为根据我的经验,许多开发人员在他们的代码中不自觉地混淆了这两者,这会导致之后出现问题。 此外,org.springframework.transaction.annotation.Transactional 提供比javax.transaction.Transactional 更多的选项(如readOnlytimeout @yura,你发现了什么问题? @LeeCheeKiam 请看下面两个答案

以上是关于javax.transaction.Transactional 与 org.springframework.transaction.annotation.Transactional的主要内容,如果未能解决你的问题,请参考以下文章