This tutorial shows an example on programmatic transaction management in Spring. The declarative transaction management example uses two approaches – annotation based and XML based configurations. You can use as per your needs.

For introduction on Spring Transaction please go through Spring Transaction
Create a table in MySQL

CREATE TABLE `items` (
  `item_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `item_name` varchar(45) COLLATE latin1_general_ci NOT NULL,
  `item_desc` text COLLATE latin1_general_ci,
  `item_price` double unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`item_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

 

Dump some data

insert into `items`(`item_id`,`item_name`,`item_desc`,`item_price`)
values (1,'CD','CD is a compact disk',100),
(2,'DVD','DVD is larger than CD in size',150),
(3,'ABC','ABC test description',24),
(4,'XYZ','XYZ test description',25.32),
(5,'CD Player','CD player is used to play CD',30.02),
(6,'New Item1','New Item1 Desc',125);

 

Using PlatformTransactionManager

The DataSourceTransactionManager bean which we have declared in the applicationContext.xml files, is of type of PlatformTransactionManager. Hence we can directly use to handle programmatic transactions.

WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    <context:annotation-config></context:annotation-config>
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="jdbc.properties">
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverclassname="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}">
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="itemDao" class="in.sblog.spring.dao.ItemDaoImpl"></bean>
    <bean id="itemService" class="in.sblog.spring.service.ItemServiceImpl"></bean>
</beans>

 

Following is a Dao class that uses PlatformTransactionManager. The code can be seen in addItem, updateItem and deleteItem method. So lets understand
Step 1 is to create an object of DefaultTransactionDefinition. This object exposes various setter methods to configure the transaction accordingly.
Step 2 is to to create the TransactionStatus object using the transaction definition we creataed in Step 1. Eventually this TransactionStatus will be used to commit or rollback the transaction like platformTransactionManager.commit(transactionStatus); or platformTransactionManager.rollback(transactionStatus);

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class ItemDaoImpl implements ItemDao {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    PlatformTransactionManager transactionManager;
    @Override
    public List getItems() {
        String sql = "SELECT * FROM items";
        List items = new ArrayList();
        items = jdbcTemplate.query(sql, new ItemRowMapper());
        return items;
    }
    @Override
    public void addItem(Item item) {
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        TransactionStatus transactionStatus = transactionManager
                .getTransaction(transactionDefinition);
        try {
            String sql = "INSERT INTO items(item_id, item_name, item_desc, item_price) VALUES (?, ?, ?, ?);";
            jdbcTemplate.update(
                    sql,
                    new Object[] { item.getItemId(), item.getItemName(),
                            item.getItemDesc(), item.getItemPrice() });
            transactionManager.commit(transactionStatus);
        } catch (Exception ex) {
            transactionManager.rollback(transactionStatus);
        }
    }
    @Override
    public void updateItem(Item item) {
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        TransactionStatus transactionStatus = transactionManager
                .getTransaction(transactionDefinition);
        try {
            String sql = "UPDATE items SET item_name=?, item_desc=?, item_price=? WHERE item_id=?;";
            jdbcTemplate.update(
                    sql,
                    new Object[] { item.getItemName(), item.getItemDesc(),
                            item.getItemPrice(), item.getItemId() });
            transactionManager.commit(transactionStatus);
        } catch (Exception ex) {
            transactionManager.rollback(transactionStatus);
        }
    }
    @Override
    public void deleteItem(Item item) throws Exception {
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition(
                TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager
                .getTransaction(transactionDefinition);
        try {
            String sql = "DELETE FROM items WHERE item_id=?;";
            jdbcTemplate.update(sql, new Object[] { item.getItemId() });
            transactionManager.commit(transactionStatus);
        } catch (Exception ex) {
            ex.printStackTrace();
            transactionManager.rollback(transactionStatus);
        }
    }
}

 

Service class

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public class ItemServiceImpl implements ItemService {
    @Autowired
    ItemDao itemDao;
    @Override
    public List getItems() {
        return itemDao.getItems();
    }
    @Override
    public void addItem(Item item) {
        itemDao.addItem(item);
    }
    @Override
    public void updateItem(Item item) {
        itemDao.updateItem(item);
    }
    @Override
    public void deleteItem(Item item) throws Exception {
        itemDao.deleteItem(item);
    }
}

 

Using Transaction Template

Spring TransactionTemplate is similar to JdbcTemplate and is used to abstract away the boilerplate code from the user. It provides simple callback methods which are automatically wrapped in a transaction. It also exposes direct setter methods for configuring various properties of transactions like setRollbackOnly etc. The Spring’s TransactionTemplate is initialized by providing a reference of DataSourceTransactionManager bean.

WEB-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    <context:annotation-config></context:annotation-config>
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="jdbc.properties">
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverclassname="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}">
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="itemDao" class="in.sblog.spring.dao.ItemDaoImpl"></bean>
    <bean id="itemService" class="in.sblog.spring.service.ItemServiceImpl"></bean>
</beans>

 

Using TransactionTemplate, we dont need to create a TransactionDefinition and Transaction object. The TransactionTemplate provides a callback method called execute where in we write our business logic that we want to wrap in a transaction. There are two types of callback methods that we can use to wrap our code i.e TransactionCallbackWithoutResult and TransactionCallback(T).

Change in ItemDaoImpl.java only and all other classes remain same.

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class ItemDaoImpl implements ItemDao {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    TransactionTemplate transactionTemplate;
    @Override
    public List getItems() {
        String sql = "SELECT * FROM items";
        List items = new ArrayList();
        items = jdbcTemplate.query(sql, new ItemRowMapper());
        return items;
    }
    @Override
    public void addItem(final Item item) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(
                    TransactionStatus transactionStatus) {
                try {
                    String sql = "INSERT INTO items(item_id, item_name, item_desc, item_price) VALUES (?, ?, ?, ?);";
                    jdbcTemplate.update(sql,
                            new Object[] { item.getItemId(),
                                    item.getItemName(), item.getItemDesc(),
                                    item.getItemPrice() });
                } catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                }
            }
        });
    }
    @Override
    public void updateItem(final Item item) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(
                    TransactionStatus transactionStatus) {
                try {
                    String sql = "UPDATE items SET item_name=?, item_desc=?, item_price=? WHERE item_id=?;";
                    jdbcTemplate.update(
                            sql,
                            new Object[] { item.getItemName(),
                                    item.getItemDesc(), item.getItemPrice(),
                                    item.getItemId() });
                } catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                }
            }
        });
    }
    @Override
    public void deleteItem(final Item item) throws Exception {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(
                    TransactionStatus transactionStatus) {
                try {
                    String sql = "DELETE FROM items WHERE item_id=?;";
                    jdbcTemplate.update(sql, new Object[] { item.getItemId() });
                } catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                }
            }
        });
    }
}

 

Thanks for your reading please do not forget to leave a comment.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *