java 自动提交和@Transactional 以及带有 spring、jpa 和 hibernate 的级联

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1834759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 18:11:03  来源:igfitidea点击:

autocommit and @Transactional and Cascading with spring, jpa and hibernate

javahibernatespringormjpa

提问by subes

what I would like to accomplish is the following:

我想完成的是以下内容:

  1. have autocommit enabled so per default all queries get commited
  2. if there is a @Transactional on a method, it overrides the autocommit and encloses all queries into a single transaction, thus overriding the autocommit
  3. if there is a @Transactional method that calls other @Transactional annotated methods, the outer most annotation should override the inner annotaions and create a larger transaction, thus annotations also override eachother
  1. 启用自动提交,因此默认情况下所有查询都会提交
  2. 如果方法上有@Transactional,它会覆盖自动提交并将所有查询包含在一个事务中,从而覆盖自动提交
  3. 如果有一个@Transactional 方法调用其他@Transactional 注解的方法,最外层的注解应该覆盖内部的注解并创建一个更大的事务,因此注解也会相互覆盖

I am currently still learning about spring-orm and couldn't find documentation about this and don't have a test project for this yet.

我目前仍在学习 spring-orm 并且找不到关于此的文档,并且还没有针对此的测试项目。

So my questions are:

所以我的问题是:

  • What is the default behaviour of transactions in spring?
  • If the default differs from my requirement, is there a way to configure my desired behaviour?
  • Or is there a totally different best practice for transactions?
  • spring中事务的默认行为是什么?
  • 如果默认值与我的要求不同,有没有办法配置我想要的行为?
  • 或者是否有完全不同的交易最佳实践?

--EDIT--

- 编辑 -

I have the following test-setup:

我有以下测试设置:

@javax.persistence.Entity
public class Entity {
  @Id
  @GeneratedValue
  private Integer id;
  private String name;
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

@Repository
public class Dao {
  @PersistenceContext
  private EntityManager em;
  public void insert(Entity ent) {
    em.persist(ent);
  }
  @SuppressWarnings("unchecked")
  public List<Entity> selectAll() {
    List<Entity> ents = em.createQuery("select e from " + Entity.class.getName() + " e").getResultList();
    return ents;
  }
}

If I have it like this, even with autocommit enabled in hibernate, the insert method does nothing. I have to add @Transactional to the insert or the method calling insert for it to work...

如果我像这样,即使在休眠中启用了自动提交,插入方法也不会执行任何操作。我必须将 @Transactional 添加到插入或调用插入的方法中才能使其工作...

Is there a way to make @Transactional completely optional?

有没有办法让@Transactional 完全可选?

采纳答案by Bozho

  • you can't have queries without an active transaction in hibernate
  • @Transactionalhas a propagationattribute, which identifies the transaction behaviour when new methods are called. The default is REQUIRED, which is what you want. Hereyou can find a graphical presentation of the concept.
  • you can omit using @Transactionalif you set-up your transactional methods with aop, like this:

    <aop:config>
        <aop:pointcut id="serviceMethods"
            expression="execution(* com.company.product.service..*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
    </aop:config>
    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
    

    That makes all public methods in the servicepackage transactional.

  • 在休眠状态下,如果没有活动事务,您将无法进行查询
  • @Transactional有一个propagation属性,用于标识调用新方法时的事务行为。默认为REQUIRED,这就是您想要的。在这里您可以找到该概念的图形演示。
  • @Transactional如果使用 aop 设置事务方法,则可以省略 using ,如下所示:

    <aop:config>
        <aop:pointcut id="serviceMethods"
            expression="execution(* com.company.product.service..*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
    </aop:config>
    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
    </tx:advice>
    

    这使得service包中的所有公共方法都是事务性的。

Also, feel free to read the entire chapter on spring transactions.

另外,请随意阅读有关 spring 事务的整章。