Transaction Management
is one of the Best Features in Spring Framework now i am going to demonstrate
in the following posts as Simple Concepts with Example Codes.
1. Introduction to
Spring Transaction Management
2. Transaction
Models in Spring
3. Transaction
Propagation in Spring
4. Examples on
Spring Transaction Management(using xml & annotations)
5. Example on
Spring Transaction Management with Hibernate and Mysql(using Annotations)
Introduction to Spring Transaction Management:
"The Process Of Combining Related Operations into Single Unit and Execute Them in 'Do Every Thing or Nothing' Manner Called 'Transaction Management'".
Transaction Management
have 3 Phases..
- Start Transaction.
- Process Transaction.
- Commit or Rollback Transaction.
As shown in the above
Diagram... Based on the Instruction coming from "Transactional Component" the 'TransactionManager' commit or rollback the application data into Database(resource)
through 'Resource Manager'.
NOTE: The Application in
which Transaction Management is enabled is known as 'Transactional
Component or Transactional App'.
Types of Transactions:
Based on The Number of
resources(Database) involved Transactions are Categorized into 2 Types
1. Local Transactions.
2. Global or Distributed
Transactions.
If there is only one Resource(Database) Involved in Transaction Then That
Transaction is Called Local
Transaction.
Ex: Transferring Money
Between Same Bank Accounts.
If There are Multiple Types of Resources(Databases) or Number of Same Type Resources(Databases) Involved in Transaction that Transaction
is Called Global or Distributed
Transaction.
Ex: Transferring Money
Between Different Bank Accounts.
Global or Distributed
Transaction Works By Using "2PC(2
Phase Commit.)" Protocol,
There are 2 Levels in
This Protocol
In 1st
level The Distributed Transaction Manager seeks Permission
from the
resources(Databases) to commit the Transaction.
In 2nd
Level if all the resources gives Permission to Commit then
the
Distributed Transaction will be Committed otherwise it will be
rolled
back.
The flow of 2PC Protocol
Spring, EJB and Hibernate Supports Local Transactions.
Only Spring and EJB supports Global or Distributed Transactions.
Transaction Models in Spring:
There are 2 Types of
Transaction Models
1. Flat
Transactions.
2. Nested
Transactions.
A Flat Transaction is One Which Treats all operations of a transaction as one transaction,and
if one operations fails then the entire Transaction will be Rolled back.
Transaction {
Operation 1
Operation 2
Operation 3
.
.
}
If any one of the above
operations failed then the entire transaction will be rolled back.
A Nested Transaction is one which Considers each operation in
Transaction as sub Transaction of that Main Transaction.If any one of the Sub
Transaction(operation) fails no impact on the Main Transaction.
Main Transaction{
sub transaction 1{
Operation 1
}
sub transaction 2{
Operation 2
}
sub transaction 3{
Operation 3
}
.
.
}
If any one of the above
sub Transaction failed no Effect on Main Transaction.
NOTE: Spring, EJB and Hibernate Supports Flat Transactions.
Only Spring supports Nested Transactions.
Transaction Propagation in Spring:
"Making a Business Method working with client
supplied Transaction
is called 'Transaction Propagation'."
There are 6 types of "Transaction Propagation"
attributes..
1. REQUIRED
2. REQUIRES NEW
3. SUPPORTS
4. NOT SUPPORTED
5. MANDATORY
6. NEVER
REQUIRED: If Client Calls Service(Business) Method having this attribute
with Transaction then Service Method runs with That Transaction else Service
Method runs with new Transaction.This is Most Popularly used Attributed.
REQUIRES NEW: Service Method having this attribute Always Runs with
new Transaction Even though the Client calls with Transaction or without
Transaction.
SUPPORTS: Service Method having this attribute
runs with Transaction if Client Calls with Transaction.
runs with out Transaction if Client Calls with out
Transaction.
NOT SUPPORTED: Service Method having this attribute Always Runs with
out Transaction Even though the Client calls with Transaction or without
Transaction.
MANDATORY: The Client Should always call Service
Method having this attribute with Transaction otherwise Exception will be raised.
NEVER: The Client Should always call Service
Method having this attribute with out Transaction otherwise Exception will be raised.
NOTE: The Programmatic Transaction
Management approach Does not support to this Transaction Propagation where
Declarative Transaction Management Supports.
Examples on Spring Transaction Management (using xml &
annotations):
In Spring There are 2 ways to use Transaction Management
1. Programmatic.
2. Declarative.
Programmatic Approach is outdated now so I don't want to discuss
it. So we move to Declarative Approach. In Declarative Approach There are 2
ways...
Using Xml Configurations.
Using Annotations.
Let me use 'Xml Configurations' in my following Eg. Application.
Example on Spring Transaction Management
using 'Xml Configurations':
In My Example i am taking
Demo(I)
DemoBean(C)
Spring.cfg.xml(Spring configuration file)
DemoClient(Class To Run Application)
and mysql database.
Demo:
package p1;
public interface Demo {
public void bm1();
}
DemoBean:
package p1;
import
org.springframework.jdbc.core.JdbcTemplate;
public class DemoBean
implements Demo{
private JdbcTemplate jt;
/**
*
@param jt the jt to set
*/
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
@Override
public void bm1() {
int r1=jt.update("insert into Employee
(eid,name,salary) values(2012,'Arjun1',100000)");
int r2=jt.update("UPDATE Employee set
salary=50000 where eid=2010");
if(r1==0 || r2==0){
System.out.println("Transaction is
Rollbacked.");
throw new RuntimeException();
}else{
System.out.println("Tx is
Committed.");
}
}
}
DemoClient:
package p1;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.FileSystemXmlApplicationContext;
public class DemoClient {
public static void main(String s[]){
/*FileSystemResource res=new
FileSystemResource("Spring.cfg.xml");
XmlBeanFactory factory=new
XmlBeanFactory(res);
Demo
d=(Demo)factory.getBean("tfb");
d.bm1();*/
ApplicationContext ctx=new
FileSystemXmlApplicationContext("Spring.cfg.xml");
Demo d=(Demo) ctx.getBean("tfb");
d.bm1();
}
}
Note: You can use Either BeanFactory or ApplicationContext
container.
Spring.cfg.xml:
<beans
xmlns="http://www.springframework.org/schema/beans"
....">
<bean id="dmds"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property
name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property
name="url" value="jdbc:mysql://localhost:3306/database
name"/>
<property
name="username" value="username"/>
<property
name="password" value="password"></property>
</bean>
<bean id="dts"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref
bean="dmds"/></property>
</bean>
<bean id="jt1"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dmds"/>
</bean>
<bean
id="db" class="p1.DemoBean">
<property name="jt" ref="jt1"/>
</bean>
<!--
Pointcut Advisor to apply Transaction Attributes. -->
<bean
id="tas"
class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="bm1">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!--
Gives Proxy Object having Transaction Service. -->
<bean
id="tfb"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target" ref="db"/>
<property name="transactionManager" ref="dts"/>
<property name="transactionAttributeSource"
ref="tas"/>
</bean>
</beans>
Run it from DemoClient.
Example on Spring Transaction Management
using 'Annotations':
In this Example I take..
Demo(I)
DemoBean(C)
Spring.cfg.xml(Spring configuration file)
DemoClient(Class To Run Application)
and mysql database.
all are same as above Application Except these Changes
in DemoBean add @Transactional annotation on top of bm1() as
shown below
@Transactional(propagation=Propagation.REQUIRED)
public void
bm1()
{.....
.....
...}
2. The Spring Configuration file is as Follows
<beans....>
<bean
id="drds"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/databasename"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
<bean
id="txmgr"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="drds"/>
</bean>
<bean
id="jt1"
class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="drds"/>
</bean>
<bean
id="db" class="p1.DemoBean">
<property name="jt" ref="jt1"/>
</bean>
<tx:annotation-driven transaction-manager="txmgr"/><!--
Enables Annotation Based Transaction Management. -->
</beans>
Run it with these Changes.
Example on Spring Transaction Management with Hibernate and
Mysql(using Annotations):
In this post i would like to discuss about Spring Tx.Magmt with
Annotations with "Spring + Hibernate + Mysql "
In
this Example i take
Demo(I)
DemoBean(c)
DemoClient(c)
Spring.xml(Spring
configuration file.)
hibernate.cfg.xml(Hibernate
configuration file.)
Employee.hbm.xml(Hibernate
Mapping File.)
Demo:
package p1;
public interface Demo {
public void
bm1()throws RuntimeException,Exception;
}
DemoBean:
package p1;
public class DemoBean
implements Demo{
private SessionFactory sf;
/**
*
@param sf the sf to set
*/
public void setSf(SessionFactory sf) {
this.sf = sf;
}
@Override
@Transactional(propagation=Propagation.REQUIRED)
public void bm1()throws Exception {
Session session=sf.getCurrentSession();
int r1=session.createQuery("UPDATE
Employee set salary=1 where sno=6").executeUpdate();
int r2=session.createQuery("UPDATE
Employee set name='kkk' where sno=57").executeUpdate();
if(r1==0 || r2==0){
System.out.println("Tx is rolling
back.");
throw new RuntimeException();
}else{
System.out.println("Tx is
Committed");
}
}
}
Spring.xml:
<beans...
.....>
<tx:annotation-driven transaction-manager="hbt"/>
<bean
id="mySessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="configLocation"
value="hibernate.cfg.xml"/>
<property name="dataSource"
ref="drds" />
</bean>
<bean
id="drds"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/TEST"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
<bean
id="hbt"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory"
ref="mySessionFactory"/>
</bean>
<bean
id="db" class="p1.DemoBean">
<property name="sf" ref="mySessionFactory"/>
</bean>
</beans>
hibernate.cfg.xml
<?xml
version="1.0" encoding="utf-8"?>
<!DOCTYPE
hibernate-configuration PUBLIC
"-//Hibernate/Hibernate
Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property
name="hibernate.connection.url">jdbc:mysql://localhost:3306/databasename</property>
<property
name="hibernate.connection.username">username</property>
<property
name="hibernate.connection.password">password</property>
<property
name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property
name="hibernate.connection.autocommit">false</property>
<property
name="hibernate.show_sql">true</property>
<mapping
resource="Employee.hbm.xml" />
</session-factory>
</hibernate-configuration>
Employee.hbm.xml:
<?xml
version="1.0"?>
<!DOCTYPE
hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class
name="p1.Employee" table="Employee" catalog="database
name">
<id name="sno" type="java.lang.Integer">
<column name="sno" />
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="name" length="30"
not-null="true" />
</property>
<property name="salary" type="float">
<column name="salary" precision="8"
not-null="true" />
</property>
<property name="eid" type="int">
<column name="eid" not-null="true" />
</property>
</class>
</hibernate-mapping>
DemoClient:
package p1;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class DemoClient {
public static void main(String s[]){
ApplicationContext ctx=new
ClassPathXmlApplicationContext("Spring.cfg.xml");
Demo d=(Demo)ctx.getBean("db");
try {
d.bm1();
} catch (RuntimeException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Run
it.

0 comments:
Post a Comment