最佳实践是在Spring中向另一个事务性服务注入事务性服务吗?

huangapple go评论71阅读模式
英文:

Is good practice to inject Transactional service to another transactional service in Spring?

问题

我感到困惑。我发现了关于将@Service类注入到另一个@Service类中的帖子。但是如果这两个类都有@Transactional注解呢?@Transactional会产生影响,或者更好的做法是注入repositories吗?

简单示例:

@Transactional
@Service
public class BBBServiceImpl implements BBBService {
    
    private final BBBRepository bbbRepository;

    // @Autowired 构造函数,方法等...

}

第二个类:

@Transactional
@Service
public class AAAServiceImpl implements AAAService {

    private final AAARepository aaaRepository;
    private final BBBService bbbService;
    
    @Autowired
    public AAAServiceImpl(AAARepository aaaRepository, BBBService bbbService) {
        this.aaaRepository = aaaRepository;
        this.bbbService = bbbService;
    }

    // 方法等...
}

或者更好的解决方案是:

@Transactional
@Service
public class AAAServiceImpl implements AAAService {

    private final AAARepository aaaRepository;
    private final BBBRepository bbbRepository;
    
    @Autowired
    public AAAServiceImpl(AAARepository aaaRepository, BBBRepository bbbRepository) {
        this.aaaRepository = aaaRepository;
        this.bbbRepository= bbbRepository;
    }

    // 方法等...
}
英文:

I'm in consternation. I found posts about inject @Service class to another @Service class. But what if the both classes have @Transactional annotation? @Transactional makes a difference or maybe better practise is inject repositories?

Simple exmaple:

@Transactional
@Service
public class BBBServiceImpl implements BBBService {
    
    private final BBBRepository bbbRepository;

    // @Autowired constructor, methods etc...
    
}

second class:

@Transactional
@Service
public class AAAServiceImpl implements AAAService {

    private final AAARepository aaaRepository;
    private final BBBService bbbService;
    
    @Autowired
    public AAAServiceImpl(AAARepository aaaRepository, BBBService bbbService) {
        this.aaaRepository = aaaRepository;
        this.bbbService = bbbService;
    }

    // methods etc...
}

Or better solution is:

@Transactional
@Service
public class AAAServiceImpl implements AAAService {

    private final AAARepository aaaRepository;
    private final BBBRepository bbbRepository;
    
    @Autowired
    public AAAServiceImpl(AAARepository aaaRepository, BBBRepository bbbRepository) {
        this.aaaRepository = aaaRepository;
        this.bbbRepository= bbbRepository;
    }

    // methods etc...

}

答案1

得分: 3

一般来说,_类_不应该是事务性的,而是它们的方法应该是。如果涉及的内容需要事务性,您应该应用 @Transactional。有时这意味着您将组合多个级别,因为您可以看到即使从个别来看,这些部分也需要 @Transactional。有时这意味着堆栈中只有一个级别需要它。您必须根据软件的逻辑要求来确定。

适用 @Transactional 的一种情况是当您有一个协调订单发货的服务时;标记订单发货的更新和写入包裹信息应该在事务中完成。因此,OrderHandlingService#shipParcel 应该是 @Transactional,而且涉及数据处理的任何方法也应该是。

英文:

In general, classes shouldn't be transactional but rather their methods. You should apply @Transactional if the item concerned needs transactionality. Sometimes this means that you'll compose multiple levels, because you can see that even individually the pieces need @Transactional. Sometimes it means that only one level in the stack needs it. You must determine based on the logical requirements of your software.

A case where it makes sense to apply @Transactional is where you have a service that coordinates shipment of orders; the updates to mark the order shipped and to write the parcel information should happen transactionally. Therefore, OrderHandlingService#shipParcel should be @Transactional, and so should any methods involving data handling.

答案2

得分: 1

理想情况下,**管理器(Manager)**代表着您的业务逻辑,因此应该使用@Transactional进行注解。

服务层可能会调用不同的DAO来执行数据库操作。假设您在一个服务方法中有3个DAO操作。如果您的第一个DAO操作失败,其他两个操作可能仍会继续执行,这将导致不一致的数据库状态。对服务层进行注解可以避免这种情况。

这还取决于传播和隔离级别的值。

即使您想要继续使用相同的事务,但在服务B中,它的传播级别是**Propagation.REQUIRES_NEW**,它将创建一个新的事务并执行业务。

英文:

Ideally, Service layer (Manager) represents your business logic and hence it should be annotated with @Transactional.

Service layer may call different DAOs to perform DB operations. Lets assume a situation where you have 3 DAO operations in a service method. If your 1st DAO operation failed, other two may be still passed and you will end up with an inconsistent DB state. Annotating Service layer can save you from such situations.

Also it's depends on Propagation and Isolation values as well.

Even though you want to continue with same transaction but on service B it's Propagation is Propagation.REQUIRES_NEW it will create new transaction and perform business.

答案3

得分: 0

可以的。因为你可以在一个服务内部调用另一个服务,无论它是否是事务性的都可以。没有问题,并且是推荐的做法。

英文:

Yes you can. Since you can call another service inside a service even it is transactional or not. No problem & recommended

huangapple
  • 本文由 发表于 2020年8月22日 03:05:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/63528735.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定