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

15,579
  • you can't have queries without an active transaction in hibernate
  • @Transactional has a propagation attribute, which identifies the transaction behaviour when new methods are called. The default is REQUIRED, which is what you want. Here you can find a graphical presentation of the concept.
  • you can omit using @Transactional if 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 service package transactional.

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

Share:
15,579
subes
Author by

subes

Updated on June 04, 2022

Comments

  • subes
    subes almost 2 years

    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

    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.

    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?

    --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...

    Is there a way to make @Transactional completely optional?

  • subes
    subes over 14 years
    hmm, ok that would work, seems like the idea I had about using autocommit was a bad idea anyway. I think it would be better practice for me to just annotate the services propertly. autocommit on any db operation would too easily lead to a broken state. instead of doing a blacklist approach I should go with a whitelist (metaphorical). I will try to create an advice that adds @Transactional to all beans annotated with @Service. Though first read about spring-aop. :) thanks
  • subes
    subes over 14 years
    the advice for transactional was a bad idea afterall: -- ibm.com/developerworks/java/library/… -- stackoverflow.com/questions/1882959/… -- my solution is to only annotate methods that do write operations and leave the rest not annotated. Adding propagation=SUPPORTS and readonly=true would maybe increase performance with hibernate, but that is currently too much effort for me to put into an aspectj CTW aspect.
  • polve
    polve about 12 years
    I have just had problems like this, and found your reference to readOnly=true and propagation=SUPPORTS. Just a word of warning: ibm.com/developerworks/java/library/j-ts1/index.html#N101B1 it doesn't work that way.