views:

902

answers:

1

Hi,

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?

+1  A: 
  • 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.

Bozho
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