Spring Programmatic Transactions by PlatformTransactionManager

Spring Programmatic Transactions by PlatformTransactionManager

All other spring transaction tutorials:

Spring Framework provides two ways to manage programmatic transaction list shown below:

  • By using TransactionTemplate.
  • By using PlatformTransactionManager implementation directly to the code.

If you are thinking to do transaction handling programmatically then spring framework recommends use of TransactionTemplate. PlatformTransactionManager implementation approach is same as using JTA UserTransaction API (Only exception handlings are less cumbersome).

We already discussed programmatic transaction handling using TransactionTemplate in our previouse post here. Today we will discuss about how to handle programmatic transaction using PlatformTransactionManager.

Below are needed to run this example:

  • Eclipse ( We are using eclipse Kepler. You could also download eclipse from eclipse.org/downloads)
  • MySQL data base (Install MySQL Community Server (GPL) version in your system : MySQL Community Server). We are using version 5.6 ( If you are not sure how to install it please use this link : Install MySQL server )
  • Maven 3.0.4

Below are steps:

Step 1. Create table to MySQL database: Please use below script to create table and insert sample data for test to the MySQL database:

DROP TABLE person
GO

CREATE TABLE person (
    id int NOT NULL AUTO_INCREMENT,
    First_Name  varchar(25) NULL,
    Last_Name   varchar(25) NULL,
    Street_Name varchar(25) NULL,
    City        varchar(25) NULL,
    State       varchar(25) NULL,
    Country     varchar(25) NULL,
    PRIMARY KEY (id) 
    )
GO

 

Step 2: Create dynamic web project in eclipse name: SpringDeclarativeTransactionAnnotaion (Please use this link if you are not sure how to create maven project in eclipse: Create  maven project in eclipse) . Maven project structure:

Spring Programmatic Transactions by PlatformTransactionManager

 

Step 3: Create Spring/resources folder inside src/main/resources. Now lets create application-config.xml to complete our XML file configuration. See below copy paste below code in your application-config.xml file

<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- DataSource to connect mysql database -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost:3306/JavaHonk"></property>
    <property name="username" value="root"></property>
    <property name="password" value="admin"></property>
</bean>

<!-- JdbcTemplate bean to execute query-->
 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
 </bean>

<!-- PlatformTransactionManager which are going to drive transaction-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- Our main DAO class bean object which we are making transactional -->
 <bean id="personDAO" class="com.javahonk.dao.PersonDAO">
    <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    <property name="platformTransactionManager" ref="transactionManager"></property>    
 </bean>          

</beans>

 

Step 4: Create three package inside src folder

  • com.javahonk
  • com.javahonk.dao
  • com.javahonk.di.bean

Step 5: Create interface IPersonDAO inside com.javahonk.dao package. This will be our service interface and we will make all method of this interface transactional. Please copy paste below code:

package com.javahonk.dao;

import com.javahonk.di.bean.Person;

public interface IPersonDAO {
    int insertUser(Person person) throws Exception;
    void deletePerson(int personID) throws Exception;
    void selectAllPerson() throws Exception;
    void selectPersonByName() throws Exception;
    
}

 

Step 6: Create implementation of above interface and where we will implement all of its method and provide details implementation of transaction. Create class PersonDAO implements IPersonDAO inside com.javahonk.dao package

package com.javahonk.dao;

import java.sql.Types;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

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 com.javahonk.di.bean.Person;

public class PersonDAO implements IPersonDAO {

    private JdbcTemplate jdbcTemplate;
    private PlatformTransactionManager platformTransactionManager;

    @Override
    public int insertUser(Person person) throws Exception {
    //Create TransactionDefinition
    DefaultTransactionDefinition defaultTransactionDefinition = 
        new DefaultTransactionDefinition();
    //Set name of your transaction
    defaultTransactionDefinition.setName("deletePersonTransaction");
    //Set transaction properties. Here we are setting 
    //PROPAGATION_REQUIRED - (Support current transaction. Ceate 
    //new one if not exists. This is analogous to EJB transaction
    //attribute with the same name. This one is default setting of
    //transaction definition and typically defines transaction
    //synchronization scope.
    defaultTransactionDefinition.setPropagationBehavior(
        TransactionDefinition.PROPAGATION_REQUIRED);
    //Retrieve transaction status information and to programmatically 
    //request roll-back
    TransactionStatus status = platformTransactionManager.
        getTransaction(defaultTransactionDefinition);
    int value;
    try {
        String inserQuery = "INSERT INTO person(First_Name, "
            + "Last_Name, Street_Name, City, State, Country) "
            + "VALUES(?, ?, ?, ?, ?, ?)";
        Object[] params = new Object[] { person.getFirstName(),
            person.getLastName(),
            person.getStreet(), person.getCity(), 
            person.getState(), person.getCountry() };
        int[] types = new int[] { Types.VARCHAR, Types.VARCHAR,
            Types.VARCHAR, Types.VARCHAR,
            Types.VARCHAR, Types.VARCHAR };
        value = jdbcTemplate.update(inserQuery, params, types);
        //commit transaction
        platformTransactionManager.commit(status);
        System.out.println("\nPerson inserted to the table");
        
    } catch (Exception e) {
        e.printStackTrace();
        platformTransactionManager.rollback(status);
        throw e;
    }
    return value;
    }

    @Override
    public void deletePerson(int personID) throws Exception {
    
    //Create TransactionDefinition
    DefaultTransactionDefinition defaultTransactionDefinition = 
        new DefaultTransactionDefinition();
    //Set name of your transaction
    defaultTransactionDefinition.setName("deletePersonTransaction");
    //Set transaction properties. Here we are setting 
    //PROPAGATION_REQUIRED - (Support current transaction. Ceate 
    //new one if not exists. This is analogous to EJB transaction
    //attribute with the same name. This one is default setting of
    //transaction definition and typically defines transaction
    //synchronization scope.
    defaultTransactionDefinition.setPropagationBehavior(
        TransactionDefinition.PROPAGATION_REQUIRED);
    //Retrieve transaction status information and to programmatically 
    //request roll-back
    TransactionStatus status = platformTransactionManager.
        getTransaction(defaultTransactionDefinition);
    
    try {
        String deletePerson = "DELETE FROM person WHERE id =?";
        Object[] params = new Object[] { personID };
        int[] types = new int[] { Types.VARCHAR };
        jdbcTemplate.update(deletePerson, params, types);
        //commit transaction
        platformTransactionManager.commit(status);
        System.out.println("\nPerson with id 1 deleted from " + "the table\n");
        
    } catch (Exception e) {
        e.printStackTrace();
        platformTransactionManager.rollback(status);
        throw e;       
    }

    }

    @Override
    //Important: For select statement we don't need any transaction
    //because we are not changing anything into the database
    //only we are setting transaction definition
    public void selectAllPerson() throws Exception {
    
    //Create TransactionDefinition
        DefaultTransactionDefinition defaultTransactionDefinition = 
            new DefaultTransactionDefinition();
        //Set name of your transaction
        defaultTransactionDefinition.setName("selectAllPersonTransaction");
        //Set transaction properties. Here we are setting 
        //ISOLATION_REPEATABLE_READ - It means dirty reads and 
        //non-repeatable reads will be prevented but phantom reads
        //can occur. It prohibits transaction from reading the row 
        //with uncommitted changes and also prohibits situation where 
        //one transaction reads row and second transaction alters row
        //and first transaction rereads same row getting different values 
        //second time ("non-repeatable read").
        defaultTransactionDefinition.setPropagationBehavior(
            TransactionDefinition.ISOLATION_REPEATABLE_READ);       
    try {
        System.out.println("\nList of person in the table\n");
        String selectAllPerson = "SELECT * FROM person";
        List<Map<String, Object>> listOfPerson = jdbcTemplate.
            queryForList(selectAllPerson);
        for (Iterator<Map<String, Object>> iterator = listOfPerson.
            iterator(); iterator.hasNext();) {
        Map<String, Object> map = (Map<String, Object>) 
            iterator.next();
        System.out.println(map);        
        }
        System.out.println();
        
    } catch (Exception e) {
        e.printStackTrace();
        throw e; 
    }

    }
    
    @Override 
    //Important: For select statement we don't need any transaction
    //because we are not changing anything into the database
    //only we are setting transaction definition
    public void selectPersonByName() throws Exception {
    //Create TransactionDefinition
        DefaultTransactionDefinition defaultTransactionDefinition = 
            new DefaultTransactionDefinition();
        //Set name of your transaction
        defaultTransactionDefinition.setName("deletePersonTransaction");
        //Set transaction properties. Here we are setting 
        //ISOLATION_REPEATABLE_READ - It means dirty reads and 
        //non-repeatable reads will be prevented but phantom reads
        //can occur. It prohibits transaction from reading the row 
        //with uncommitted changes and also prohibits situation where 
        //one transaction reads row and second transaction alters row
        //and first transaction rereads same row getting different values 
        //second time ("non-repeatable read").
        defaultTransactionDefinition.setPropagationBehavior(
            TransactionDefinition.ISOLATION_REPEATABLE_READ);
    
        try {
        System.out.println("\nList of person name Java "
                + "in the table\n");
        String selectAllPerson = "SELECT * FROM person where "
            + "First_Name ='Java'";
        List<Map<String, Object>> listOfPerson = jdbcTemplate.
            queryForList(selectAllPerson);
        for (Iterator<Map<String, Object>> iterator = listOfPerson.
            iterator(); iterator.hasNext();) {
        Map<String, Object> map = (Map<String, Object>) 
            iterator.next();
        System.out.println(map);
        }
        System.out.println();
        
    } catch (Exception e) {
        e.printStackTrace();
        throw e; 
    }
    
    }

    
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
    }

    public void setPlatformTransactionManager(PlatformTransactionManager 
        platformTransactionManager) {
        this.platformTransactionManager = platformTransactionManager;
    }
    

}

 

Step 7: Now create Person.java bean class which act as business object inside package com.javahonk.di.bean and copy paste below code:

package com.javahonk.di.bean;

import java.io.Serializable;

public class Person implements Serializable{

    private static final long serialVersionUID = 1L;
    private String FirstName;
    private String LastName;
    private String street;
    private String city;
    private String state;
    private String country;
    
    
    public Person(String firstName, String lastName, String street,
        String city, String state, String country) {
    super();
    FirstName = firstName;
    LastName = lastName;
    this.street = street;
    this.city = city;
    this.state = state;
    this.country = country;
    }
    
    public String getFirstName() {
        return FirstName;
    }
    public void setFirstName(String firstName) {
        FirstName = firstName;
    }
    public String getLastName() {
        return LastName;
    }
    public void setLastName(String lastName) {
        LastName = lastName;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
    

}

 

Step 8: Please add below dependencies in pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.samples.service.service</groupId>
  <artifactId>SpringMaven</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>  
    
    
    <dependencies>  
            
        <!-- Spring and Transactions -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>3.0.3.RELEASE</version>
        </dependency>
        
        <!-- MySql 5.5 Connector -->   
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.29</version>
        </dependency>
        
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.4</version>
        </dependency>
            
            
    </dependencies> 
</project>

 

Step 9: Maven project create logger file automatically but in case it’s not created then create logback.xml inside src\main\resources folder and copy paste below code in it:

<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration file for LogBack (slf4J implementation)
See here for more details: http://gordondickens.com/wordpress/2013/03/27/sawing-through-the-java-loggers/ -->
<configuration scan="true" scanPeriod="30 seconds">

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>

    <!-- To enable JMX Management -->
    <jmxConfigurator/>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%-5level %logger{0} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--<logger name="org.hibernate" level="debug"/> -->
   <!-- Uncomment and add your logger here:
    <logger name="org.springframework.samples.service.service" level="debug"/> -->
         
    <root level="info">
        <appender-ref ref="console"/>
    </root>
</configuration>

 

Step 10: Our all configuration is completed lastly create main class to test it. Create main class name: TestSpringJDBCTemplate.java inside com.javahonk package and copy paste below content in it:

package com.javahonk;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.javahonk.dao.IPersonDAO;
import com.javahonk.di.bean.Person;

public class TestSpringJDBCTemplate {

    public static void main(String[] args) throws Exception {
    
    ClassPathXmlApplicationContext applicationContext = 
        new ClassPathXmlApplicationContext(
            "spring\\application-config.xml");

    IPersonDAO personDAO = applicationContext.
        getBean("personDAO", IPersonDAO.class);
    Person person = new Person("Java", "Honk", 
        "John st.","NY", "NY", "USA");
    
    //Insert user to the table 3 times:
    for (int i = 0; i < 3; i++) {
        personDAO.insertUser(person); 
    }
    
    //Delete first person from table
    personDAO.deletePerson(1);
        
    //Select all inserted user from the table
    personDAO.selectAllPerson();    
    
    //Select data from tabel where person 
    //name is "Java"
    personDAO.selectPersonByName();
    

    applicationContext.close();

    }

}

 

Step 11: Our final project structure will look as below:

Spring Programmatic Transactions by PlatformTransactionManager

 

Step 12: Let’s test it. Right click main class TestSpringJDBCTemplate.java –> Run As –> Java Application. You will see results on the console as below:

 Spring Programmatic Transactions by PlatformTransactionManager

Step 13: Data in the table:

Spring Programmatic Transactions by PlatformTransactionManager

  • That’s it Spring Programmatic Transactions by PlatformTransactionManager completed successfully.

Spring jdbctemplate tutorial Download source code : Spring Programmatic Transactions using PlatformTransactionManager

 

Leave a Reply

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