2

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 Answer 1

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

Sign up to request clarification or add additional context in comments.

3 Comments

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.