- 浏览: 470573 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
excellent95:
谢楼主分享,确实是CSS图片问题
Struts2判断页面是POST方式提交还是GET方式提交 -
wangluo2:
javaBase那个包显示有问题啊pom文件那一行报错了
微信公众平台开发实战(08) 基于地理信息的服务(LBS) -
andilyliao:
jd技术这么渣也好意思出书,真是醉了
《京东技术解密》试读--十年磨一剑 -
bitray:
刘强东作序多什么,他也不会什么技术,腾讯出来帮他还不是因为腾讯 ...
《京东技术解密》试读--十年磨一剑 -
come_for_dream:
想试试搞这个
《大型分布式网站架构设计与实践》试读
在软件开发过程中,经常会遇到事务问题,下面我们来看看最简单的JDBC和Spring分别如何处理事务。
关于事务控制的场景当然是转账,我们使用的数据库是MySQL。
打开test数据库后,运行下面的数据库脚本:
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
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
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
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 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="accountDAO" class="com.coderdream.AccountDAO" /> <bean id="accountService" class="com.coderdream.AccountService"> <property name="accountDAO" ref="accountDAO"></property> </bean> </beans>
上面的代码是没有加事务控制的,如果把‘A’处的代码换成:
// 帐号1转账1元至帐号3 accountService.transfer(1, 3, 1);//A
则由于帐号3不存在,所以会出现问题,帐号1的金额会减1,而帐号2的金额不会变,转账的1元就“不翼而飞”了,所以必须在Dao层加入事务控制。
代码5:加入事务控制后的AccountDAO
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
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 version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.coderdream.Account" table="account" catalog="test"> <id name="accountId" type="java.lang.Integer"> <column name="accountId" /> <generator class="native" /> </id> <property name="accountname" type="java.lang.String"> <column name="accountname" length="20" /> </property> <property name="money" type="java.lang.Integer"> <column name="money" length="20" /> </property> </class> </hibernate-mapping>
代码8:
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:
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:
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
<?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
<?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层的要使用的方法上声明事务,如:
@Transactional(readOnly = false)
如果只是对数据库进行查询操作,这里的“readOnly = true“,如果是”增/删/改“操作,则为 false。
代码13:在方法上加入“注解式”事务控制后的 AccountService.java
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 */ @Transactional(readOnly = false) public void transfer(Integer fromAccountId, Integer toAccountId, int money) { accountDAO.subMoney(fromAccountId, money); accountDAO.addMoney(toAccountId, money); } }
- TransDemo.rar (6 MB)
- 下载次数: 166
发表评论
-
Spring Security 3.0 记住密码功能
2016-01-13 22:58 20621,在数据库中新增记录表 -- ---------- ... -
解决JavaMail发邮件抛出找不到SharedByteArrayInputStream类的异常
2011-07-22 11:21 7408在最近项目开发过程中 ... -
怎样让Word自动更新图片与表格编号
2010-12-31 17:03 11665怎样让Word 自动更新图片与表格编号 ... -
W3C_School在线教程chm版制作教程
2010-12-22 21:48 7633W3C_School 在线教程chm 版制作教程 ... -
String与StringBuffer区别详解
2010-12-17 17:19 3245String 与StringBuffe ... -
Spring 3.0 新特性
2010-12-10 10:58 3357Spring 3.0 新特性 ... -
iText生成PDF时表头设置错误导出数据不能完全导出
2010-07-20 12:16 2145在利用iText生成PDF文件时,通常由于数据量比较多时会产生 ... -
JavaMail
2009-07-16 16:56 0javamail 怎样设置发件人的名字 http://to ... -
IBM Ajax系列教程
2009-02-16 20:39 1706第 1 部分: Ajax 简介 Ajax ... -
项目经验之弹出页面再弹出页面
2009-02-13 18:58 1060在项目中有这样一个场景,某弹出页面要弹出另一个: 弹出页面: ... -
正则表达式使用之替换多个字符串
2009-02-13 15:44 2531想一次性去掉某个文本文件中的某些字符串: 实现方式: 直接用竖 ... -
OGNL的jar档、文档和源代码
2009-02-05 09:25 51861、官方网站: http://mirrors.ibiblio. ... -
Calendar与java.sql.Date
2008-12-08 15:29 1660在Oracle数据库中,我们会有Date类型的数据,存储格 ... -
利用JavaScript控制单选框
2008-12-04 19:14 2273<script> function f(index ... -
JSP中使用JavaScript重定向页面
2008-12-03 10:04 3325第一种,不重定向,推荐使用。 function init( ... -
如何去掉 Code Pro 的警告标志
2008-11-07 16:35 1307Code Pro 是一个很好的代码格式检查工具,不过有时我们只 ... -
使用Struts提交多行数据
2008-11-07 11:27 3881使用Struts提交多行数据 http://blog.fl ... -
Ant使用经验
2008-10-22 10:18 12561、【示例1】: <?xml version=" ... -
利用JXL(JExcelApi)操作Excel文档
2008-10-09 10:51 51821、工具类: package com.coderdream. ... -
JSP下载文档
2008-10-07 14:08 18841、设置doc格式的文件弹出对话框: <?xml v ...
相关推荐
两个项目,一个项目是基于spring jdbc实现的分布式事务,一个是基于spring hibernate的分布式事务,hibernate项目里的applicationContext2.xml是基于mysql和mssql, applicationContext3.xml基于两个mssql, ...
这是一个Dynamic Web Project,主要使用hibernate和spring框架,其中事务管理使用的是注解。 hibernate的版本:hibernate-distribution-3.6.6.Final; spring的版本:spring-framework-3.1.0.M2 。 注意:此项目没有...
spring3.2+strut2+hibernate4 注解方式。 spring.xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=...
spring mvc + spring + hibernate 全注解整合开发视频教程 11
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <value>...
spring-jdbc-orm基于spring-jdbc 写的一个小型ORM设计初衷由于公司现有的代码工程经历了无数人的手,原来的初衷已经变了模样,可以说乱的让我不能接受,代码中大部分都使用了Map封装实体信息,有伤大雅,大部分业务...
使用Spring注解方式管理事务与传播行为详解 24.使用Spring配置文件实现事务管理 25.搭建和配置Spring与Hibernate整合的环境 26.Spring集成的Hibernate编码与测试 27.Struts与Spring集成方案1(Struts集成Spring) ...
struts2:struts2-convention-plugin-2.3.1.2.jar ---注解开发 struts2-spring-plugin-2.3.1.2.jar---用于整合spring hibernate:hibernate3.jar---核心包 hibernate-release-4.3.1.Final\lib\required\*.jar ...
2,配置声明式事务(使用基于注解的方式) 1,配置 <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> ...
开始spring之旅;装配bean;创建切面;使用Aspectj进行AOP开发;使用pojo+xml进行AOP开发;征服数据库-jdbc;征服数据库-集成hibernate;...事务管理-spring2.5配置方式;事务管理-注解驱动事务等等。
9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring JDBC包结构...
弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件。本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,...
10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼 10.6.1 哪些方法不能实施Spring AOP事务 10.6.2 事务增强遗漏实例 10.7 数据连接泄漏 10.7.1 底层连接资源的访问问题 10.7.2 Spring JDBC...
Java Transaction API (JTA)、JDBC、Hibernate 和 Java Persistence API (JPA) 等事务 API,实现了一致的编程模型,而 Spring 的声明式事务功能更是提供了极其方便的事务配置方式,配合 Spring Boot 的自动配置,...
9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. 选择一...
9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. 选择一种...
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <value>...
第9章:介绍了Spring事务管理的工作机制,通过XML、注解等方式进行事务管理配置,同时还讲解了JTA事务配置知识。 第10章:对实际应用中Spring事务管理各种疑难问题进行透彻的剖析,让读者对Spring事务管理不再有...
45. 使用 Spring 通过什么方式访问 Hibernate? 46. Spring 支持的 ORM 47.如何通过 HibernateDaoSupport 将 Spring 和 Hibernate 结合起来? 48. Spring 支持的事务管理类型 49. Spring 框架的事务管理有哪些优点?...