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


当前回答

总的来说,我同意其他人的说法,事务通常在服务级别上启动(当然,这取决于您需要的粒度)。

然而,与此同时,我也开始在我的DAO层(以及其他不允许启动事务但需要现有事务的层)中添加@Transactional(propagation = propagation . mandatory),因为当您忘记在调用者(例如服务)中启动事务时,检测错误要容易得多。如果您的DAO带有强制传播注释,则会得到一个异常,说明在调用方法时没有活动事务。

我还进行了一个集成测试,在该测试中,我检查了所有bean (bean后处理器)的该注释,如果在不属于服务层的bean中存在传播方式不是Mandatory的@Transactional注释,则会失败。这样可以确保我们不会在错误的层上启动事务。

其他回答

我更喜欢在方法级的服务层上使用@Transactional。

@Transactional应该用于服务层,因为它包含业务逻辑。DAO层通常只有数据库CRUD操作。

// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {

    Foo getFoo(String fooName);

    Foo getFoo(String fooName, String barName);

    void insertFoo(Foo foo);

    void updateFoo(Foo foo);
}

春季文档:https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html

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

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

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

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