< Prev
Next >



Spring with Hibernate Transaction by Proxy



In our last tutorial we explained how to configure and perform transaction management within the database using Spring Framework and Hibernate with Schema. In this tutorial, we are going to explain how to configure and perform transaction management within the database using Spring Framework and Hibernate with Proxy classes.

For this approach, we will have to configure a bean of org.springframework.transaction.interceptor.TransactionProxyFactoryBean class. This class is a subclass of ProxyFactoryBean class, which creates the proxy class for the target class at the runtime to take care of the transaction operations. The target class is the class that has methods for performing the transaction operations. Let's understand everything with an example.




Difference between Spring-Hibernate transaction by Annotation and Spring-Hibernate transaction by Proxy


The difference between two approaches is that when we perform transaction management within the database using Spring Framework with Hibernate and Annotation, we need an access to the source code to edit it and add @Transactional Annotation to class and methods involved in transaction operations.

But, in case of performing transaction management within the database using Spring Framework with Hibernate and Proxy, we will have to configure a bean of org.springframework.transaction.interceptor.TransactionProxyFactoryBean class using the configuration xml file. This class is a subclass of ProxyFactoryBean class, which creates the proxy class for the target class at the runtime to take care of the transaction operations.




What Spring-Hibernate transaction management by Proxy does?


The transaction management involves managing database transaction operations such as -

The Spring-Hibernate transaction management by Proxy makes sure :






Note :


Before we proceed with the example of database transaction management, we would first need to configure Spring Framework to work with Hibernate. To perform this, we will use a very important template class provided by Spring Framework, named - HibernateTemplate, which provides different methods for querying and retrieving data from the database.




Creating the Java class - Customer_Account


We are going to create a java class named Customer within the decodejava package and this class contains - Besides this, we are also going to define a couple of getter and setter methods within this class to set the above mentioned properties of Customer class.


package decodejava;

public class Customer_Account 
{
	int id;
	String name;
	int amount;
	int age;
	
	
	public String getName() 
	{
		return name;
	}
	
	
	public void setName(String name) 
	{
		this.name = name;
	}
	
	
	public int getAmount() {
		return amount;
	}


	public void setAmount(int amount) {
		this.amount = amount;
	}


	public int getAge() 
	{
		return age;
	}
	
	
	public void setAge(int age) 
	{
		this.age = age;
	}
	
	
	public int getId() 
	{
		return id;
	}


	public void setId(int id) 
	{
		this.id = id;
	}

}





Class performing data access operations(DAO) using Spring


Next, we are going to add another Java class named CustomerDAO this class will contain separate methods to perform database operations such as -

Besides the above mentioned database operations, this class will also contain separate methods to perform transaction operations such as -


This class is also going to contain a HibernateTemplate property named hibernateTemplate, used to configure Hibernate with Spring. This hibernateTemplate property will be assigned a value by the Spring Container using its respective setter methods, when the CustomerDAO bean is created by it using the configuration xml file(to be created in the upcoming section).




package decodejava;

import java.util.List;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;


public class CustomerDAO 
{
private HibernateTemplate hibernateTemplate;
	
	
	//Getter for HibernateTemplate
	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	
	//Setter for HibernateTemplate
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) 
	{
		this.hibernateTemplate = hibernateTemplate;
	}
	
	
	//Adding a customer
	public void addCustomer(Customer_Account c)
	{
		hibernateTemplate.save(c);
	}
	
	
	//Deleting a customer
	public void deleteCustomer(int id)
	{		
		Customer_Account c=hibernateTemplate.get(Customer_Account.class,id);
		hibernateTemplate.delete(c);
	}
	
	
	//Extracting a count of all the customers
	public int countCustomer()
	{
		List<Customer_Account> list =hibernateTemplate.loadAll(Customer_Account.class); 
		return list.size();
		
	}
	
	
	//Getting a List of all customers from database
	public List<Customer_Account> getAllCustomer()
	{		
		List<Customer_Account> list =hibernateTemplate.loadAll(Customer_Account.class);  
		return list;
	}
	
	
	//Transaction method i.e. depositing an amount in an account
	public void depositAmount(int id, int amount)
	{
		Customer_Account cust = getHibernateTemplate().get(Customer_Account.class, id);
		cust.setAmount(cust.getAmount() + amount);
		getHibernateTemplate().update(cust);		
	}
	
	
	
	
	//Transaction method i.e. withdrawing an amount from an account
	public void withdrawAmount(int id, int amount)
	{
		Customer_Account cust = getHibernateTemplate().get(Customer_Account.class, id);
		cust.setAmount(cust.getAmount() - amount);
		getHibernateTemplate().update(cust);				
	}
}





Adding the Utility class that calls the Spring API


Next, we are going to create another class named - Utility, which is a simple java class.

Utility.java
package decodejava;



import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Utility {

	public static void main(String[] args) 
	{
		ApplicationContext context = new FileSystemXmlApplicationContext("classpath:config.beans.xml");
		CustomerDAO customerDAO = context.getBean("CustomerDAOProxyBean",CustomerDAO.class);
		
		
		System.out.println("Creating a table in database");
		customerDAO.createTable();
		
		
		System.out.println("Adding the customers");
		customerDAO.addCustomer(1, "First Customer", 1000, 23);
		customerDAO.addCustomer(2, "Second Customer", 2000, 27);
		customerDAO.addCustomer(3, "Third Customer", 3000, 21);
		
		
		System.out.println("Getting all the customers from the database");
		List<Customer_Account> allCustomers = customerDAO.getAllCustomer();
		for(Customer_Account cust : allCustomers)
		{
			System.out.println("Customer ID : " + cust.getId());
			System.out.println("Customer Name : " + cust.getName());
			System.out.println("Customer Balance Amount : " + cust.getAmount());
			System.out.println("Customer Age : " + cust.getAge());
			
		}
	
		
		System.out.println("Getting the total count of all the Customers");
		System.out.println("Total Customers : " + customerDAO.countCustomer());
		
		
		System.out.println("Deleting a Customer with id = 2");
		customerDAO.deleteCustomer(2);
		
		System.out.println("Getting the new total count of all the Customers after deleting a customer");
		System.out.println("Total Customers : " + customerDAO.countCustomer());
	
		
		System.out.println("A customer with id = 1, is depositing an amount of 20000");
		customerDAO.depositAmount(1, 20000);
		
		System.out.println("A customer with id = 3, is withdrawing an amount of 500");
		customerDAO.withdrawAmount(3, 500);
		
		
		
		System.out.println("Getting all the customers from the database and their updated amount :");
		List<Customer_Account> allCustomers2 = customerDAO.getAllCustomer();
		for(Customer_Account cust : allCustomers2)
		{
			System.out.println("Customer ID : " + cust.getId());
			System.out.println("Customer Name : " + cust.getName());
			System.out.println("Customer Balance Amount : " + cust.getAmount());
			System.out.println("Customer Age : " + cust.getAge());
			                                                           
		}
		
	}

}


The Utility class uses the ApplicationContext container(an interface) of Spring Framework by creating its instance using its implemented class FileSystemXmlApplicationContext, which loads the configuration xml file - config.beans.xml and does the following -






Adding a configuration file


Next, we are going to add a configuration file to our project. This configuration document is an Extensible Markup Language(XML) file, ending with .xml extension and we are going to name file as config.beans.xml.

In this file, we have configured a CustomerDAO bean with a unique id and its HibernateTemplate property named HibernateTemplate. These property will be assigned a value by the Spring Container using its respective setter methods, when the CustomerDAO bean is created by it using the configuration xml file.


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


           
<bean id="CustomerDAOBean" class="decodejava.CustomerDAO">
<property name="hibernateTemplate" ref="hibernateTemplateBean"></property>
</bean>


<bean id="hibernateTemplateBean" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="SessionFactoryBean"></property>
<property name="checkWriteOperations" value="false"/>
</bean>



<bean id="CustomerDAOProxyBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target" ref="CustomerDAOBean"></property>
<property name="proxyTargetClass" value="true"></property>
<property name="transactionManager" ref="txnManagerBean"></property>
<property name="transactionAttributes">
	<props>
		<prop key="addCustomer">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception</prop>
		<prop key="deleteCustomer">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception</prop>
		<prop key="depositAmount">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception</prop>
		<prop key="withdrawAmount">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception</prop>
	</props>
</property>
</bean>



<bean id="txnManagerBean" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactoryBean"></property>
</bean>



<bean id="SessionFactoryBean" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSourceBean"></property>
<property name="mappingResources" value="customer_account.hbm.xml"></property>
<property name="hibernateProperties">
	<value>
	hibernate.hbm2ddl.auto=create
	hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
	hibernate.show_sql=true
	hibernate.default_schema=system
	</value>>
</property>
</bean>


<bean id="dataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"></property>
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="username" value="scott"></property>
<property name="password" value="tiger"></property>
</bean>


</beans>



This mapping document has a parent <beans> tag as the root element and its individual child elements, each with a <bean> tag, containing all the attributes such as -



Understanding the proxy bean in the configuration xml file


In order to support the transaction operations, we have configured a bean of org.springframework.transaction.interceptor.TransactionProxyFactoryBean class. This class is a subclass of ProxyFactoryBean class, which creates the proxy class for the target class at the runtime to take care of the transaction operations. The target class is CustomerDAO class that has methods for performing the transaction operations. Let's take its syntax from configuration xml file.


<bean id="CustomerProxyBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target" ref="CustomerDAOBean"></property>
<property name="proxyTargetClass" value="true"></property>
<property name="transactionManager" ref="txManagerBean"></property>
<property name="transactionAttributes">
	<props>
		<prop key="addCustomer">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception></prop>
		<prop key="deleteCustomer">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception></prop>
		<prop key="depositAmount">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception></prop>
		<prop key="withdreamAmount">PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT, -Exception></prop>
	</props>
</property>
</bean>


  1. A Propagation constant i.e. PROPAGATION_REQUIRES_NEW. It is used to specify the transaction behaviour i.e. PROPAGATION_REQUIRES_NEW specifies that a method should be executed in a new transaction.

  2. An Isolation constant i.e. ISOLATION_DEFAULT. This constant specifies the way of configuring the concurrent transactions i.e. ISOLATION_DEFAULT specifies that a default isolation levels defined in relational databases..

  3. An Exception constant with a plus(+) or minus(-) sign i.e. -Exception. This constant specifies the checked exception classes and when any of the specified exceptions are thrown, the associated transaction will be rolled back immediately.






Adding JARs








Directory Structure of Project




The picture above depicts how and where to arrange classes and interfaces comprising this Spring Project, in a specific directory structure.

Project Folder - SpringWithHibernateTransactionByProxy is the name of our Project and it is a top-level directory.






Execution


Finally, after executing Utility class, you will get the following output within the Console window. This output shown below, shows how the Utility class has used the ApplicationContext container of Spring Framework to load the configuration xml file - config.beans.xml, access the beans specified in it, instantiate the CustomerDAO class and performs JDBC operations by calling the methods of CustomerDAO class.


Aug 11, 2018 3:52:22 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@26f0a63f: startup date [Sat Aug 11 15:52:22 2018]; root of context hierarchy
Aug 11, 2018 3:52:22 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config.beans.xml]
Aug 11, 2018 3:52:24 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName
INFO: Loaded JDBC driver: oracle.jdbc.driver.OracleDriver
Aug 11, 2018 3:52:24 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.2.17.Final}
Aug 11, 2018 3:52:24 PM org.hibernate.cfg.Environment 
INFO: HHH000206: hibernate.properties not found
Aug 11, 2018 3:52:24 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager 
INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
Aug 11, 2018 3:52:26 PM org.hibernate.dialect.Dialect 
INFO: HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
Hibernate: create sequence system.hibernate_sequence start with 1 increment by  1
Hibernate: create table system.Customer_Account (ID number(10,0) not null, Age number(10,0), Amount number(10,0), Name varchar2(255 char), primary key (ID))
Aug 11, 2018 3:52:28 PM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@672f11c2'
Aug 11, 2018 3:52:28 PM org.springframework.orm.hibernate5.HibernateTransactionManager afterPropertiesSet
INFO: Using DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource@3e1162e7] of Hibernate SessionFactory for HibernateTransactionManager

Adding the customers
Hibernate: select system.hibernate_sequence.nextval from dual
Hibernate: insert into system.Customer_Account (Age, Amount, Name, ID) values (?, ?, ?, ?)
Hibernate: select system.hibernate_sequence.nextval from dual
Hibernate: insert into system.Customer_Account (Age, Amount, Name, ID) values (?, ?, ?, ?)
Hibernate: select system.hibernate_sequence.nextval from dual
Hibernate: insert into system.Customer_Account (Age, Amount, Name, ID) values (?, ?, ?, ?)

Getting all the customers from the database
Hibernate: select this_.ID as ID1_0_0_, this_.Age as Age2_0_0_, this_.Amount as Amount3_0_0_, this_.Name as Name4_0_0_ from system.Customer_Account this_
Customer ID : 1
Customer Name : First Customer
Customer Balance Amount : 1000
Customer Age : 23
Customer ID : 2
Customer Name : Second Customer
Customer Balance Amount : 2000
Customer Age : 27
Customer ID : 3
Customer Name : Third Customer
Customer Balance Amount : 3000
Customer Age : 21

Getting the total count of all the Customers
Hibernate: select this_.ID as ID1_0_0_, this_.Age as Age2_0_0_, this_.Amount as Amount3_0_0_, this_.Name as Name4_0_0_ from system.Customer_Account this_
Total Customers : 3

Deleting a Customer
Hibernate: select customer_a0_.ID as ID1_0_0_, customer_a0_.Age as Age2_0_0_, customer_a0_.Amount as Amount3_0_0_, customer_a0_.Name as Name4_0_0_ from system.Customer_Account customer_a0_ where customer_a0_.ID=?
Hibernate: delete from system.Customer_Account where ID=?

Getting the new total count of all the Customers after deleting a customer
Hibernate: select this_.ID as ID1_0_0_, this_.Age as Age2_0_0_, this_.Amount as Amount3_0_0_, this_.Name as Name4_0_0_ from system.Customer_Account this_
Total Customers : 2

A customer with id = 1, is depositing an amount of 20000
Hibernate: select customer_a0_.ID as ID1_0_0_, customer_a0_.Age as Age2_0_0_, customer_a0_.Amount as Amount3_0_0_, customer_a0_.Name as Name4_0_0_ from system.Customer_Account customer_a0_ where customer_a0_.ID=?
Hibernate: update system.Customer_Account set Age=?, Amount=?, Name=? where ID=?

A customer with id = 3, is withdrawing an amount of 500
Hibernate: select customer_a0_.ID as ID1_0_0_, customer_a0_.Age as Age2_0_0_, customer_a0_.Amount as Amount3_0_0_, customer_a0_.Name as Name4_0_0_ from system.Customer_Account customer_a0_ where customer_a0_.ID=?
Hibernate: update system.Customer_Account set Age=?, Amount=?, Name=? where ID=?

Getting all the customers from the database
Hibernate: select this_.ID as ID1_0_0_, this_.Age as Age2_0_0_, this_.Amount as Amount3_0_0_, this_.Name as Name4_0_0_ from system.Customer_Account this_
Customer ID : 1
Customer Name : First Customer
Customer Balance Amount : 21000
Customer Age : 23
Customer ID : 3
Customer Name : Third Customer
Customer Balance Amount : 2500
Customer Age : 21


And, this concludes performing transaction management by configuring Spring Framework with Hibernate using Proxy classes.




Please share this article -

Facebook Google Pinterest Reddit Tumblr Twitter



< Prev
Next >
< Spring-Hibernate TS By Schema
Aspect Oriented Programming(AOP) >
Please subscribe our social media channels for notifications, we post a new article everyday.

Decodejava Google+ Page Decodejava Facebook Page  DecodeJava Twitter Page

Coming Next
-
C++ and Python

Ad2