您应该将@Transactional放在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的服务类?或者对两个“层”都加注释有意义吗?


当前回答

事务注释应该放在所有不可分割的操作周围。

例如,你的呼叫是“change password”。它由两个操作组成

修改密码。 审计变更。 通过电子邮件通知客户端密码已更改。

那么在上面,如果审计失败,那么修改密码也应该失败吗?如果是这样,那么事务应该在1和2左右(因此在服务层)。如果电子邮件失败了(可能应该有某种故障安全措施,这样它就不会失败),那么它是否应该回滚更改密码和审计?

在决定将@Transactional放在哪里时,您需要询问这些问题。

其他回答

理想情况下,服务层(管理器)表示业务逻辑,因此应该用@Transactional进行注释。服务层可以调用不同的DAO来执行DB操作。让我们假设在一个服务方法中有N个DAO操作。如果您的第一个DAO操作失败,其他DAO操作可能仍然通过,您将以不一致的DB状态结束。注释服务层可以避免这种情况。

服务层中的@事务使用是通过使用控制器层(@Controller)调用的,服务层调用DAO层(@Repository),即数据库相关的操作。

通常,应该将事务放在服务层。

但是正如前面所述,操作的原子性告诉我们哪里需要注释。因此,如果你使用像Hibernate这样的框架,其中一个“save/update/delete/…”一个对象上的“modify”操作有可能修改几个表中的几行(因为通过对象图的级联),当然在这个特定的DAO方法上也应该有事务管理。

最好将@Transactional放在DAO和服务层之间的单独中间层中。 由于回滚非常重要,您可以将所有的DB操作放在中间层,并在服务层中编写业务逻辑。中间层将与DAO层交互。

这将帮助您在许多情况下,如ObjectOptimisticLockingFailureException -此异常只发生在您的事务结束后。所以,你不能在中间层捕获它,但你现在可以在服务层捕获它。如果在服务层中有@Transactional,这是不可能的。虽然你可以在控制器中捕获,但控制器应该尽可能干净。

如果您在完成所有保存、删除和更新选项后在单独的线程中发送邮件或短信,您可以在中间层事务完成后在服务中执行此操作。同样,如果你在服务层提到@Transactional,即使你的事务失败,你的邮件也会被发送。

所以有一个中间的@Transaction层将有助于使你的代码更好,更容易处理。否则, 如果在DAO层使用,可能无法回滚所有操作。 如果在服务层使用,在某些情况下可能必须使用AOP(面向方面编程)。

此外,Spring建议只在具体的类上使用注释,而不是在接口上使用。

http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html