Search This Blog

Friday 5 October 2012

Programattic Transactions

In the previous post we saw how Spring allows us to use advices for transaction management. However Spring also provides support for programatically managing transactions.
public class TestProgramatticClient {

    private IPersonDAO personDAO;
    private TransactionTemplate transactionTemplate;
    
    public void savePerson(final Person person) {        
        transactionTemplate.execute(new TransactionCallback<Void>() {
            public Void doInTransaction(final TransactionStatus txStatus) {
                try {
                    personDAO.save(person);
    
                } catch (RuntimeException e) {
                    txStatus.setRollbackOnly();
                    throw e;
                }
                return null;
            }
        });
    }
}
In the above we have used no advices - no transparent method level transactions. We have explicitly specified our transaction boundaries. This was achieved by using Spring's TransactionTemplate.
Similar to the database template classes in Spring, The TransactionTemplate class also uses a callback mechanism. It exposes a doInTransaction method that takes a TransactionStatus as parameter and is capable of returning an object. (Uses generics)
The TransactionStatus class represents the status of a transaction. Transactional code can use this to retrieve status information and to programmatically request a rollback like we have done in the above code. There is no commit method available. If the doInTransaction() method completes successfully, then the transaction will be committed.
The TransactionTemplate needs to be wired into the bean:
<bean id="testProgClient" class="com.test.TestProgramatticClient">
    <property name="transactionTemplate">
        <bean class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager" />
        </bean>
    </property>
    <property name="personDAO" ref="personDAO"/>
</bean>
The test method is as below:
public static void main(String[] args) {
    final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-prog-txn.xml");
    final TestProgramatticClient hibClient =  (TestProgramatticClient) applicationContext.getBean("testProgClient");
    Person person = new Person();
    person.setName("Raj");
    person.setAge(26);
    hibClient.savePerson(person);
}
The logs indicate successful execution of the method within transactional boundaries.
4438 [main] DEBUG org.springframework.orm.hibernate3.HibernateTransactionManager  
- Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
4516 [main] DEBUG org.springframework.orm.hibernate3.HibernateTransactionManager  
- Opened new Session [org.hibernate.impl.SessionImpl@3e1bc8] for Hibernate transaction
4516 [main] DEBUG org.springframework.orm.hibernate3.HibernateTransactionManager  
- Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@3e1bc8]
4547 [main] DEBUG org.springframework.orm.hibernate3.HibernateTransactionManager  
- Exposing Hibernate transaction as JDBC transaction [com.mchange.v2.c3p0.impl.NewProxyConnection@10c0f66]
...
4578 [main] DEBUG org.springframework.transaction.support.TransactionSynchronizationManager  
- Initializing transaction synchronization
...
4750 [main] DEBUG org.springframework.orm.hibernate3.HibernateTransactionManager  
- Triggering beforeCompletion synchronization
4750 [main] DEBUG org.springframework.orm.hibernate3.HibernateTransactionManager  
- Initiating transaction commit
4750 [main] DEBUG org.springframework.orm.hibernate3.HibernateTransactionManager  
- Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@3e1bc8]

No comments:

Post a Comment