事务管理入门-JDBC/Hibernate事务管理器/Spring注解 3种方式

本文介绍了三种事务管理方式:JDBC中的事务控制、Spring+Hibernate的事务管理器托管以及Spring中的注解方式。通过转账实例详细展示了每种方式的具体实现。

事务管理入门-JDBC/Hibernate事务管理器/Spring注解 3种方式

在软件开发过程中,经常会遇到事务问题,下面我们来看看最简单的JDBC和Spring分别如何处理事务。

 

关于事务控制的场景当然是转账,我们使用的数据库是MySQL。

打开test数据库后,运行下面的数据库脚本:

Sql代码 复制代码  收藏代码
  1. DROP TABLE IF EXISTS account;   
  2. CREATE TABLE account (   
  3. accountId int primary key auto_increment,   
  4. accountname varchar(20),   
  5. money int not null  
  6. );   
  7.   
  8. INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('zhangsan',100);   
  9. INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('lisi',100);  
DROP TABLE IF EXISTS account;
CREATE TABLE account (
accountId int primary key auto_increment,
accountname varchar(20),
money int not null
);

INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('zhangsan',100);
INSERT INTO ACCOUNT(ACCOUNTNAME,MONEY) VALUES('lisi',100);
 

1、JDBC中的事务控制

 

代码1:AccountDAO.java

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. import java.sql.Connection;   
  4. import java.sql.DriverManager;   
  5. import java.sql.ResultSet;   
  6. import java.sql.SQLException;   
  7. import java.sql.Statement;   
  8.   
  9. public class AccountDAO {   
  10.   
  11.     public void transfer(Integer fromAccountId, Integer toAccountId, int money) {   
  12.         try {   
  13.             // 1. 注册驱动   
  14.             Class.forName("com.mysql.jdbc.Driver");   
  15.   
  16.             // 2. 获取数据库的连接   
  17.             Connection conn = DriverManager.getConnection(   
  18.                     "jdbc:mysql://localhost/test""root""1234");   
  19.   
  20.             // 3. 获取表达式   
  21.             Statement stmt1 = conn.createStatement();   
  22.             Statement stmt2 = conn.createStatement();   
  23.             Statement stmt3 = conn.createStatement();   
  24.             Statement stmt4 = conn.createStatement();   
  25.   
  26.             // 执行插入数据的 SQL   
  27.             ResultSet rs1 = stmt1   
  28.                     .executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="  
  29.                             + fromAccountId);   
  30.             // 5. 显示结果集里面的数据   
  31.             int money1 = 0;   
  32.             while (rs1.next()) {   
  33.                 System.out.println(rs1.getInt(1));   
  34.                 money1 = rs1.getInt(1);   
  35.             }   
  36.   
  37.             // 修改   
  38.             money1 -= money;   
  39.             System.out.println("money1: " + money1);   
  40.             stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money1   
  41.                     + " WHERE ACCOUNTID=" + fromAccountId);   
  42.   
  43.             // 执行插入数据的 SQL   
  44.             ResultSet rs2 = stmt3   
  45.                     .executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="  
  46.                             + toAccountId);   
  47.             // 5. 显示结果集里面的数据   
  48.             int money2 = 0;   
  49.             while (rs2.next()) {   
  50.                 System.out.println(rs2.getInt(1));   
  51.                 money2 = rs2.getInt(1);   
  52.             }   
  53.   
  54.             // 修改   
  55.             money2 += money;   
  56.             System.out.println("money2: " + money2);   
  57.             stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money2   
  58.                     + " WHERE ACCOUNTID=" + toAccountId);   
  59.   
  60.             // 6. 释放资源   
  61.             rs1.close();   
  62.             rs2.close();   
  63.             stmt1.close();   
  64.             stmt2.close();   
  65.             stmt3.close();   
  66.             stmt4.close();   
  67.             conn.close();   
  68.         } catch (ClassNotFoundException e) {   
  69.             e.printStackTrace();   
  70.         } catch (SQLException e) {   
  71.             e.printStackTrace();   
  72.         }   
  73.   
  74.     }   
  75. }  
package com.coderdream;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class AccountDAO {

	public void transfer(Integer fromAccountId, Integer toAccountId, int money) {
		try {
			// 1. 注册驱动
			Class.forName("com.mysql.jdbc.Driver");

			// 2. 获取数据库的连接
			Connection conn = DriverManager.getConnection(
					"jdbc:mysql://localhost/test", "root", "1234");

			// 3. 获取表达式
			Statement stmt1 = conn.createStatement();
			Statement stmt2 = conn.createStatement();
			Statement stmt3 = conn.createStatement();
			Statement stmt4 = conn.createStatement();

			// 执行插入数据的 SQL
			ResultSet rs1 = stmt1
					.executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="
							+ fromAccountId);
			// 5. 显示结果集里面的数据
			int money1 = 0;
			while (rs1.next()) {
				System.out.println(rs1.getInt(1));
				money1 = rs1.getInt(1);
			}

			// 修改
			money1 -= money;
			System.out.println("money1: " + money1);
			stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money1
					+ " WHERE ACCOUNTID=" + fromAccountId);

			// 执行插入数据的 SQL
			ResultSet rs2 = stmt3
					.executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="
							+ toAccountId);
			// 5. 显示结果集里面的数据
			int money2 = 0;
			while (rs2.next()) {
				System.out.println(rs2.getInt(1));
				money2 = rs2.getInt(1);
			}

			// 修改
			money2 += money;
			System.out.println("money2: " + money2);
			stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money2
					+ " WHERE ACCOUNTID=" + toAccountId);

			// 6. 释放资源
			rs1.close();
			rs2.close();
			stmt1.close();
			stmt2.close();
			stmt3.close();
			stmt4.close();
			conn.close();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}
}
 

代码2:AccountService.java

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. public class AccountService {   
  4.   
  5.     private AccountDAO accountDAO;   
  6.   
  7.     /**  
  8.      * 通过 Spring 向 Service ͨszh注入 Dao  
  9.      *   
  10.      * @param accountDAO  
  11.      */  
  12.     public void setAccountDAO(AccountDAO accountDAO) {   
  13.         this.accountDAO = accountDAO;   
  14.     }   
  15.   
  16.     /**  
  17.      * 转账  
  18.      *   
  19.      * @param fromAccountId  
  20.      *            转出帐号  
  21.      * @param toAccountId  
  22.      *            转入帐号  
  23.      * @param money  
  24.      *            转账金额  
  25.      */  
  26.     public void transfer(Integer fromAccountId, Integer toAccountId, int money) {   
  27.         accountDAO.transfer(fromAccountId, toAccountId, money);   
  28.     }   
  29. }  
package com.coderdream;

public class AccountService {

	private AccountDAO accountDAO;

	/**
	 * 通过 Spring 向 Service ͨszh注入 Dao
	 * 
	 * @param accountDAO
	 */
	public void setAccountDAO(AccountDAO accountDAO) {
		this.accountDAO = accountDAO;
	}

	/**
	 * 转账
	 * 
	 * @param fromAccountId
	 *            转出帐号
	 * @param toAccountId
	 *            转入帐号
	 * @param money
	 *            转账金额
	 */
	public void transfer(Integer fromAccountId, Integer toAccountId, int money) {
		accountDAO.transfer(fromAccountId, toAccountId, money);
	}
}

 

代码3:Main.java

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. import org.springframework.context.ApplicationContext;   
  4. import org.springframework.context.support.FileSystemXmlApplicationContext;   
  5.   
  6. public class Main {   
  7.   
  8.     /**  
  9.      * @param args  
  10.      */  
  11.     public static void main(String[] args) {   
  12.   
  13.         ApplicationContext act = new FileSystemXmlApplicationContext(   
  14.                 "src/applicationContext.xml");   
  15.         AccountService accountService = (AccountService) act   
  16.                 .getBean("accountService");   
  17.         try {   
  18.             // 帐号1转账1元至帐号2   
  19.             accountService.transfer(121);//A   
  20.                } catch (Exception e) {   
  21.             System.out.println("转账失败!");   
  22.         }   
  23.     }   
  24. }  
package com.coderdream;

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

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		ApplicationContext act = new FileSystemXmlApplicationContext(
				"src/applicationContext.xml");
		AccountService accountService = (AccountService) act
				.getBean("accountService");
		try {
			// 帐号1转账1元至帐号2
			accountService.transfer(1, 2, 1);//A
               } catch (Exception e) {
			System.out.println("转账失败!");
		}
	}
}
 

代码4:applicationContext.xml

Xml代码 复制代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans    
  5.     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
  6.   
  7.     <bean id="accountDAO" class="com.coderdream.AccountDAO" />  
  8.        
  9.     <bean id="accountService" class="com.coderdream.AccountService">  
  10.         <property name="accountDAO" ref="accountDAO"></property>  
  11.     </bean>  
  12. </beans>  

 

上面的代码是没有加事务控制的,如果把‘A’处的代码换成:

Java代码 复制代码  收藏代码
  1. // 帐号1转账1元至帐号3   
  2. accountService.transfer(131);//A  
			// 帐号1转账1元至帐号3
			accountService.transfer(1, 3, 1);//A

 

则由于帐号3不存在,所以会出现问题,帐号1的金额会减1,而帐号2的金额不会变,转账的1元就“不翼而飞”了,所以必须在Dao层加入事务控制。

 

代码5:加入事务控制后的AccountDAO

Java代码 复制代码  收藏代码
  1. public class AccountDAO {   
  2.   
  3.     public void transfer(Integer fromAccountId, Integer toAccountId, int money) {   
  4.         Connection conn = null;   
  5.         ResultSet rs1 = null;   
  6.         Integer rs2 = null;   
  7.         ResultSet rs3 = null;   
  8.         Integer rs4 = null;   
  9.         Statement stmt1 = null;   
  10.         Statement stmt2 = null;   
  11.         Statement stmt3 = null;   
  12.         Statement stmt4 = null;   
  13.         // 1. 注册驱动   
  14.         try {   
  15.             Class.forName("com.mysql.jdbc.Driver");   
  16.   
  17.             // 2. 获取数据库的连接   
  18.             conn = DriverManager.getConnection("jdbc:mysql://localhost/test",   
  19.                     "root""1234");   
  20.   
  21.             conn.setAutoCommit(false);   
  22.   
  23.             // 3. 获取表达式   
  24.             stmt1 = conn.createStatement();   
  25.             stmt2 = conn.createStatement();   
  26.             stmt3 = conn.createStatement();   
  27.             stmt4 = conn.createStatement();   
  28.   
  29.             // 执行插入数据的 SQL   
  30.             rs1 = stmt1   
  31.                     .executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="  
  32.                             + fromAccountId);   
  33.             // 5. 显示结果集里面的数据   
  34.             int money1 = 0;   
  35.             while (rs1.next()) {   
  36.                 System.out.println(rs1.getInt(1));   
  37.                 money1 = rs1.getInt(1);   
  38.             }   
  39.   
  40.             // 修改   
  41.             money1 -= money;   
  42.             System.out.println("money1: " + money1);   
  43.             rs2 = stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money1   
  44.                     + " WHERE ACCOUNTID=" + fromAccountId);   
  45.             if (1 != rs2) {   
  46.                 throw new Exception(" 转出失败,帐号: " + fromAccountId);   
  47.             }   
  48.   
  49.             // 执行插入数据的 SQL   
  50.             rs3 = stmt3   
  51.                     .executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="  
  52.                             + toAccountId);   
  53.             // 5. 显示结果集里面的数据   
  54.             int money2 = 0;   
  55.             while (rs3.next()) {   
  56.                 System.out.println(rs3.getInt(1));   
  57.                 money2 = rs3.getInt(1);   
  58.             }   
  59.   
  60.             // 修改   
  61.             money2 += money;   
  62.             System.out.println("money2: " + money2);   
  63.             rs4 = stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money2   
  64.                     + " WHERE ACCOUNTID=" + toAccountId);   
  65.             if (1 != rs4) {   
  66.                 throw new Exception(" 转入失败,帐号: " + toAccountId);   
  67.             }   
  68.   
  69.             conn.commit();   
  70.             System.out.println("转帐成功!");   
  71.         } catch (Exception e) {   
  72.             try {   
  73.                 conn.rollback();   
  74.             } catch (Exception e1) {   
  75.                 e1.printStackTrace();   
  76.             }   
  77.             e.printStackTrace();   
  78.         }   
  79.         // 6. 释放资源   
  80.         finally {   
  81.             try {   
  82.                 if (rs1 != null) {   
  83.                     rs1.close();   
  84.                 }   
  85.                 if (rs3 != null) {   
  86.                     rs3.close();   
  87.                 }   
  88.                 if (stmt1 != null) {   
  89.                     stmt1.close();   
  90.                 }   
  91.                 if (stmt2 != null) {   
  92.                     stmt2.close();   
  93.                 }   
  94.                 if (stmt3 != null) {   
  95.                     stmt3.close();   
  96.                 }   
  97.                 if (stmt4 != null) {   
  98.                     stmt4.close();   
  99.                 }   
  100.                 if (conn != null) {   
  101.                     conn.close();   
  102.                 }   
  103.             } catch (SQLException e) {   
  104.                 e.printStackTrace();   
  105.             }   
  106.         }   
  107.     }   
  108. }  
public class AccountDAO {

	public void transfer(Integer fromAccountId, Integer toAccountId, int money) {
		Connection conn = null;
		ResultSet rs1 = null;
		Integer rs2 = null;
		ResultSet rs3 = null;
		Integer rs4 = null;
		Statement stmt1 = null;
		Statement stmt2 = null;
		Statement stmt3 = null;
		Statement stmt4 = null;
		// 1. 注册驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");

			// 2. 获取数据库的连接
			conn = DriverManager.getConnection("jdbc:mysql://localhost/test",
					"root", "1234");

			conn.setAutoCommit(false);

			// 3. 获取表达式
			stmt1 = conn.createStatement();
			stmt2 = conn.createStatement();
			stmt3 = conn.createStatement();
			stmt4 = conn.createStatement();

			// 执行插入数据的 SQL
			rs1 = stmt1
					.executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="
							+ fromAccountId);
			// 5. 显示结果集里面的数据
			int money1 = 0;
			while (rs1.next()) {
				System.out.println(rs1.getInt(1));
				money1 = rs1.getInt(1);
			}

			// 修改
			money1 -= money;
			System.out.println("money1: " + money1);
			rs2 = stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money1
					+ " WHERE ACCOUNTID=" + fromAccountId);
			if (1 != rs2) {
				throw new Exception(" 转出失败,帐号: " + fromAccountId);
			}

			// 执行插入数据的 SQL
			rs3 = stmt3
					.executeQuery("SELECT MONEY FROM ACCOUNT WHERE ACCOUNTID="
							+ toAccountId);
			// 5. 显示结果集里面的数据
			int money2 = 0;
			while (rs3.next()) {
				System.out.println(rs3.getInt(1));
				money2 = rs3.getInt(1);
			}

			// 修改
			money2 += money;
			System.out.println("money2: " + money2);
			rs4 = stmt2.executeUpdate("UPDATE ACCOUNT SET MONEY=" + money2
					+ " WHERE ACCOUNTID=" + toAccountId);
			if (1 != rs4) {
				throw new Exception(" 转入失败,帐号: " + toAccountId);
			}

			conn.commit();
			System.out.println("转帐成功!");
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		// 6. 释放资源
		finally {
			try {
				if (rs1 != null) {
					rs1.close();
				}
				if (rs3 != null) {
					rs3.close();
				}
				if (stmt1 != null) {
					stmt1.close();
				}
				if (stmt2 != null) {
					stmt2.close();
				}
				if (stmt3 != null) {
					stmt3.close();
				}
				if (stmt4 != null) {
					stmt4.close();
				}
				if (conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}
 

2、Spring中的事务控制方式一:Hibernate的事务管理器托管

我们先来看看通过Spring+Hibernate来操作数据库的简单示例。

先通过 MyEclipse 生成Hibernate 需要的 Bean 及 hbm.xml文件:

 

代码6:Account.java

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. /**  
  4.  * Account entity.  
  5.  *   
  6.  * @author MyEclipse Persistence Tools  
  7.  */  
  8. public class Account implements java.io.Serializable {   
  9.   
  10.     /**  
  11.      *   
  12.      */  
  13.     private static final long serialVersionUID = 909891879728703117L;   
  14.   
  15.     private Integer accountId;   
  16.     private String accountname;   
  17.     private Integer money;   
  18.   
  19.     // Property accessors   
  20.   
  21.     public Integer getAccountId() {   
  22.         return this.accountId;   
  23.     }   
  24.   
  25.     public void setAccountId(Integer accountId) {   
  26.         this.accountId = accountId;   
  27.     }   
  28.   
  29.     public String getAccountname() {   
  30.         return this.accountname;   
  31.     }   
  32.   
  33.     public void setAccountname(String accountname) {   
  34.         this.accountname = accountname;   
  35.     }   
  36.   
  37.     public Integer getMoney() {   
  38.         return this.money;   
  39.     }   
  40.   
  41.     public void setMoney(Integer money) {   
  42.         this.money = money;   
  43.     }   
  44.   
  45.     // Constructors   
  46.   
  47.     /** default constructor */  
  48.     public Account() {   
  49.     }   
  50.   
  51.     /** full constructor */  
  52.     public Account(String accountname, Integer money) {   
  53.         this.accountname = accountname;   
  54.         this.money = money;   
  55.     }   
  56.   
  57. }  
package com.coderdream;

/**
 * Account entity.
 * 
 * @author MyEclipse Persistence Tools
 */
public class Account implements java.io.Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 909891879728703117L;

	private Integer accountId;
	private String accountname;
	private Integer money;

	// Property accessors

	public Integer getAccountId() {
		return this.accountId;
	}

	public void setAccountId(Integer accountId) {
		this.accountId = accountId;
	}

	public String getAccountname() {
		return this.accountname;
	}

	public void setAccountname(String accountname) {
		this.accountname = accountname;
	}

	public Integer getMoney() {
		return this.money;
	}

	public void setMoney(Integer money) {
		this.money = money;
	}

	// Constructors

	/** default constructor */
	public Account() {
	}

	/** full constructor */
	public Account(String accountname, Integer money) {
		this.accountname = accountname;
		this.money = money;
	}

}
 

代码7:Account.hbm.xml

Xml代码 复制代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!--   
  5.     Mapping file autogenerated by MyEclipse Persistence Tools  
  6. -->  
  7. <hibernate-mapping>  
  8.     <class name="com.coderdream.Account" table="account" catalog="test">  
  9.         <id name="accountId" type="java.lang.Integer">  
  10.             <column name="accountId" />  
  11.             <generator class="native" />  
  12.         </id>  
  13.         <property name="accountname" type="java.lang.String">  
  14.             <column name="accountname" length="20" />  
  15.         </property>  
  16.         <property name="money" type="java.lang.Integer">  
  17.             <column name="money" length="20" />  
  18.         </property>  
  19.     </class>  
  20. </hibernate-mapping>  
 

代码8:

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;   
  4.   
  5. public class AccountDAO extends HibernateDaoSupport {   
  6.   
  7.     public void addMoney(Integer accountId, int money) {   
  8.         Account account = (Account) getHibernateTemplate().get(Account.class,   
  9.                 accountId);   
  10.         account.setMoney(account.getMoney() + money);   
  11.         getHibernateTemplate().saveOrUpdate(account);   
  12.     }   
  13.   
  14.     public void subMoney(Integer accountId, int money) {   
  15.         Account account = (Account) getHibernateTemplate().get(Account.class,   
  16.                 accountId);   
  17.         account.setMoney(account.getMoney() - money);   
  18.         getHibernateTemplate().saveOrUpdate(account);   
  19.     }   
  20. }  
package com.coderdream;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class AccountDAO extends HibernateDaoSupport {

	public void addMoney(Integer accountId, int money) {
		Account account = (Account) getHibernateTemplate().get(Account.class,
				accountId);
		account.setMoney(account.getMoney() + money);
		getHibernateTemplate().saveOrUpdate(account);
	}

	public void subMoney(Integer accountId, int money) {
		Account account = (Account) getHibernateTemplate().get(Account.class,
				accountId);
		account.setMoney(account.getMoney() - money);
		getHibernateTemplate().saveOrUpdate(account);
	}
}
 

代码9:

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. public class AccountService {   
  4.   
  5.     private AccountDAO accountDAO;   
  6.   
  7.     /**  
  8.      * 通过 Spring 将 DAO 注入到 Service  
  9.      *   
  10.      * @param accountDAO  
  11.      */  
  12.     public void setAccountDAO(AccountDAO accountDAO) {   
  13.         this.accountDAO = accountDAO;   
  14.     }   
  15.   
  16.     /**  
  17.      * 转账方法包括两个原子方法:转出方法和转入方法  
  18.      *   
  19.      * @param fromAccountId  
  20.      * @param toAccountId  
  21.      * @param money  
  22.      */  
  23.     public void transfer(Integer fromAccountId, Integer toAccountId, int money) {   
  24.         accountDAO.subMoney(fromAccountId, money);   
  25.         accountDAO.addMoney(toAccountId, money);   
  26.     }   
  27. }  
package com.coderdream;

public class AccountService {

	private AccountDAO accountDAO;

	/**
	 * 通过 Spring 将 DAO 注入到 Service
	 * 
	 * @param accountDAO
	 */
	public void setAccountDAO(AccountDAO accountDAO) {
		this.accountDAO = accountDAO;
	}

	/**
	 * 转账方法包括两个原子方法:转出方法和转入方法
	 * 
	 * @param fromAccountId
	 * @param toAccountId
	 * @param money
	 */
	public void transfer(Integer fromAccountId, Integer toAccountId, int money) {
		accountDAO.subMoney(fromAccountId, money);
		accountDAO.addMoney(toAccountId, money);
	}
}
 

代码10:

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. import org.springframework.context.ApplicationContext;   
  4. import org.springframework.context.support.FileSystemXmlApplicationContext;   
  5.   
  6. public class Main {   
  7.   
  8.     /**  
  9.      * @param args  
  10.      */  
  11.     public static void main(String[] args) {   
  12.   
  13.         ApplicationContext act = new FileSystemXmlApplicationContext(   
  14.                 "src/applicationContext.xml");   
  15.         AccountService accountService = (AccountService) act   
  16.                 .getBean("accountService");   
  17.         try {   
  18.             // 帐号1转账1元至帐号2   
  19.             accountService.transfer(121);// B   
  20.         } catch (Exception e) {   
  21.             System.out.println("转账失败");   
  22.         }   
  23.     }   
  24. }  
package com.coderdream;

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

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		ApplicationContext act = new FileSystemXmlApplicationContext(
				"src/applicationContext.xml");
		AccountService accountService = (AccountService) act
				.getBean("accountService");
		try {
			// 帐号1转账1元至帐号2
			accountService.transfer(1, 2, 1);// B
		} catch (Exception e) {
			System.out.println("转账失败");
		}
	}
}
 

上面的代码同样没有加入事务控制,如果在‘B’处将转入的帐号设置为不存在的帐号3,同样会有问题,下面我们来加入事务控制,我们需要修改 applicationContext.xml 文件:

 

代码11:增加事务后的 applicationContext.xml

Java代码 复制代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans    
  5.     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">   
  6.   
  7.     <bean id="dataSource"  
  8.         class="org.apache.commons.dbcp.BasicDataSource">   
  9.         <property name="driverClassName"  
  10.             value="com.mysql.jdbc.Driver">   
  11.         </property>   
  12.         <property name="url" value="jdbc:mysql://localhost:3306/test"></property>   
  13.         <property name="username" value="root"></property>   
  14.         <property name="password" value="1234"></property>   
  15.     </bean>   
  16.   
  17.     <bean id="sessionFactory"  
  18.         class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">   
  19.         <property name="dataSource">   
  20.             <ref bean="dataSource" />   
  21.         </property>   
  22.         <property name="hibernateProperties">   
  23.             <props>   
  24.                 <prop key="hibernate.dialect">   
  25.                     org.hibernate.dialect.MySQLDialect   
  26.                 </prop>   
  27.                 <prop key="hibernate.show_sql">true</prop>   
  28.             </props>   
  29.         </property>   
  30.         <property name="mappingResources">   
  31.             <list>   
  32.                 <value>com/coderdream/Account.hbm.xml</value>   
  33.             </list>   
  34.         </property>   
  35.     </bean>   
  36.   
  37.     <!-- 引用Hibernate的事务管理器 -->   
  38.     <bean id="transactionManager"  
  39.         class="org.springframework.orm.hibernate3.HibernateTransactionManager">   
  40.         <property name="sessionFactory" ref="sessionFactory"></property>   
  41.     </bean>   
  42.   
  43.     <bean id="accountDAO" class="com.coderdream.AccountDAO">   
  44.         <property name="sessionFactory" ref="sessionFactory"></property>   
  45.     </bean>   
  46.   
  47.     <!-- 通过事务管理器来管理Service -->   
  48.     <bean id="accountService"  
  49.         class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">   
  50.         <property name="transactionManager" ref="transactionManager"></property>   
  51.         <property name="target">   
  52.             <bean class="com.coderdream.AccountService">   
  53.                 <property name="accountDAO" ref="accountDAO"></property>   
  54.             </bean>   
  55.         </property>   
  56.         <property name="transactionAttributes">   
  57.             <props>   
  58.                 <prop key="transfer">PROPAGATION_REQUIRED</prop>   
  59.             </props>   
  60.         </property>   
  61.     </bean>   
  62. </beans>  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName"
			value="com.mysql.jdbc.Driver">
		</property>
		<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="username" value="root"></property>
		<property name="password" value="1234"></property>
	</bean>

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>com/coderdream/Account.hbm.xml</value>
			</list>
		</property>
	</bean>

	<!-- 引用Hibernate的事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

	<bean id="accountDAO" class="com.coderdream.AccountDAO">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

	<!-- 通过事务管理器来管理Service -->
	<bean id="accountService"
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager" ref="transactionManager"></property>
		<property name="target">
			<bean class="com.coderdream.AccountService">
				<property name="accountDAO" ref="accountDAO"></property>
			</bean>
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="transfer">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
	</bean>
</beans>
 

3、Spring中的事务控制方式二:注解方式

当然,我们还可以通过注解的方式加入事务的控制。

我们需要先在 applicationContext.xml 声明事务控制器和注解:

 

代码12:applicationContext.xml

Java代码 复制代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:jee="http://www.springframework.org/schema/jee"  
  5.     xmlns:tx="http://www.springframework.org/schema/tx"  
  6.     xmlns:context="http://www.springframework.org/schema/context"  
  7.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">   
  8.   
  9.     <bean id="dataSource"  
  10.         class="org.apache.commons.dbcp.BasicDataSource">   
  11.         <property name="driverClassName"  
  12.             value="com.mysql.jdbc.Driver">   
  13.         </property>   
  14.         <property name="url" value="jdbc:mysql://localhost:3306/test"></property>   
  15.         <property name="username" value="root"></property>   
  16.         <property name="password" value="1234"></property>   
  17.     </bean>   
  18.   
  19.     <bean id="sessionFactory"  
  20.         class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">   
  21.         <property name="dataSource">   
  22.             <ref bean="dataSource" />   
  23.         </property>   
  24.         <property name="hibernateProperties">   
  25.             <props>   
  26.                 <prop key="hibernate.dialect">   
  27.                     org.hibernate.dialect.MySQLDialect   
  28.                 </prop>   
  29.                 <prop key="hibernate.show_sql">true</prop>   
  30.             </props>   
  31.         </property>   
  32.         <property name="mappingResources">   
  33.             <list>   
  34.                 <value>com/coderdream/Account.hbm.xml</value>   
  35.             </list>   
  36.         </property>   
  37.     </bean>   
  38.   
  39.     <!-- 引用Hibernate的事务管理器 -->   
  40.     <bean id="transactionManager"  
  41.         class="org.springframework.orm.hibernate3.HibernateTransactionManager">   
  42.         <property name="sessionFactory" ref="sessionFactory"></property>   
  43.     </bean>   
  44.   
  45.     <!-- 使用annotation定义事务 -->   
  46.     <tx:annotation-driven transaction-manager="transactionManager" />   
  47.   
  48.     <bean id="accountDAO" class="com.coderdream.AccountDAO">   
  49.         <property name="sessionFactory" ref="sessionFactory"></property>   
  50.     </bean>   
  51.   
  52.     <bean id="accountService" class="com.coderdream.AccountService">   
  53.         <property name="accountDAO" ref="accountDAO"></property>   
  54.     </bean>   
  55. </beans>  
<?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:jee="http://www.springframework.org/schema/jee"
	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-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<bean id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName"
			value="com.mysql.jdbc.Driver">
		</property>
		<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="username" value="root"></property>
		<property name="password" value="1234"></property>
	</bean>

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
		<property name="mappingResources">
			<list>
				<value>com/coderdream/Account.hbm.xml</value>
			</list>
		</property>
	</bean>

	<!-- 引用Hibernate的事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

	<!-- 使用annotation定义事务 -->
	<tx:annotation-driven transaction-manager="transactionManager" />

	<bean id="accountDAO" class="com.coderdream.AccountDAO">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

	<bean id="accountService" class="com.coderdream.AccountService">
		<property name="accountDAO" ref="accountDAO"></property>
	</bean>
</beans>
 

同时需要在Service层的要使用的方法上声明事务,如:

Java代码 复制代码  收藏代码
  1. @Transactional(readOnly = false)  
@Transactional(readOnly = false)

 如果只是对数据库进行查询操作,这里的“readOnly = true“,如果是”增/删/改“操作,则为 false。

 

代码13:在方法上加入“注解式”事务控制后的 AccountService.java

Java代码 复制代码  收藏代码
  1. package com.coderdream;   
  2.   
  3. public class AccountService {   
  4.   
  5.     private AccountDAO accountDAO;   
  6.   
  7.     /**  
  8.      * 通过 Spring 将 DAO 注入到 Service  
  9.      *   
  10.      * @param accountDAO  
  11.      */  
  12.     public void setAccountDAO(AccountDAO accountDAO) {   
  13.         this.accountDAO = accountDAO;   
  14.     }   
  15.   
  16.     /**  
  17.      * 转账方法包括两个原子方法:转出方法和转入方法  
  18.      *   
  19.      * @param fromAccountId  
  20.      * @param toAccountId  
  21.      * @param money  
  22.      */  
  23.     @Transactional(readOnly = false)   
  24.     public void transfer(Integer fromAccountId, Integer toAccountId, int money) {   
  25.         accountDAO.subMoney(fromAccountId, money);   
  26.         accountDAO.addMoney(toAccountId, money);   
  27.     }   
  28. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值