【问题标题】:Transactions with Spring and JPA与 Spring 和 JPA 的事务
【发布时间】:2015-08-14 05:27:51
【问题描述】:

我正在学习使用 JPA。我有点困惑。

根据 JPA EntityManager 管理事务。但是一种设计模式是在 DAO 中注入 EntityManager。那么同一个事务怎么可能有不同的EntityManager呢?

这是我要解决的情况

我已经定义了 DAO

@Repository
JPARepository1 {

    @PersistenceContext
    protected EntityManager em;

    ....   

.

@Repository
JPARepository2 {

    @PersistenceContext
    protected EntityManager em;

    ....

我有一个服务

@Service
public class ServiceImpl1 {

    @Autowired
    private JPARepository1 repo1;

    @Autowired
    private JPARepository2 repo2;  


    public void mainMethod(){
        Object o= transactionalMethod1();

        try{
            transactionalMethod2(o);
        }catch (Exception e){
            transactionalMethod3(o);
        }

    }

    private Object transactionalMethod1(){
        ....
    }

    private void transactionalMethod2(Object o){
        ....
    }


    private void transactionalMethod3(Object o){
        ....
    }

然后我将从@Controller 调用mainMethod()。 在同一个服务中并使用同一个存储库,对 transactionalMethod1、transactionalMethod2 和 transactionalMethod3 进行事务处理的正确方法是什么。 如果 transactionalMethod2 中有异常,我希望它中止事务,但保留 transactionalMethod1 和 transactionalMethod3 的事务 谢谢,对不起我的英语

【问题讨论】:

  • 谁说传入的EntityMangers 不一样?
  • 嗯,我不知道。那么单例和所有 DAO 都使用相同的 EntityManger 吗?
  • 我相信EntityManager 可能不止一个,但对于您的简单情况,您可以期望只有一个。

标签: java spring hibernate jpa


【解决方案1】:

通常您配置一个 EntityManager,因此有线管理器始终是相同的,即您配置的那个。不过,这个管理器的实例在每条线路中都不同。

因此,您的服务中的每个事务都使用不同的 EntityManager 实例,因此调用的每个事务都是彼此分离的。

因此,transactionalMethod2 中的异常不一定会影响 transactionalMethod1transactionalMethod3

在同一个服务中并使用同一个存储库,对 transactionalMethod1、transactionalMethod2 和 transactionalMethod3 进行事务处理的正确方法是什么。

现在,你有两个选项可以做服务方法transactions

1) 你可以像这样注释你的整个@Service

@Service
@Transactional
public class ServiceImpl1 {
....

所以这里声明的每个方法也是一个事务

2)您可以将每个方法注释为@Transactional

@Transactional
private Object transactionalMethod1(){
    ....
}

@Transactional
private void transactionalMethod2(Object o){
    ....
}

@Transactional
private void transactionalMethod3(Object o){
    ....
}

如果您想使用单个存储库,只需 @Autowired 一个并在您的 @Transactional 方法中使用它。例如:

@Service
@Transactional
public class ServiceImpl1 {

@Autowired
private JPARepository1 repo1; 

public void mainMethod(){
    Object o= transactionalMethod1();

    try{
        transactionalMethod2(o);
    }catch (Exception e){
        transactionalMethod3(o);
    }

}

private Object transactionalMethod1(){
    return repo1.findOne();
}

private void transactionalMethod2(Object o){
    repo1.create(o);
}


private void transactionalMethod3(Object o){
    repo1.delete(o)
}

【讨论】:

  • 每个事务服务必须使用不同的EntityManager,因为它不是线程安全的。当您自动装配 EntityManager 时,实际上是自动装配代理,它为您提供池中的 EntityManager 实例。
  • 所以transactionalMethod 是事务性的吗?他们不需要用 @transacional 注释需要新的选项或其他东西吗?
  • 谢谢,我必须在另一个服务中定义transactionalMethod?这个link 说“这意味着只有通过代理进入的外部方法调用才会被拦截——任何自调用都不会启动任何事务”
  • 没有。这篇文章引用了一个服务层设计模式,您可以在其中为您的服务创建一个interface,而您的@Service 类实现了interface。当您在 @Controller 中使用该模式而不是 autowiring service implementationautowiring interface 它实现
猜你喜欢
  • 2018-03-10
  • 2013-04-10
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 2020-03-07
  • 2013-05-30
  • 1970-01-01
  • 2017-12-23
相关资源
最近更新 更多