- 浏览: 478512 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
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 21171,在数据库中新增记录表 -- ---------- ... -
解决JavaMail发邮件抛出找不到SharedByteArrayInputStream类的异常
2011-07-22 11:21 7726在最近项目开发过程中 ... -
怎样让Word自动更新图片与表格编号
2010-12-31 17:03 11750怎样让Word 自动更新图片与表格编号 ... -
W3C_School在线教程chm版制作教程
2010-12-22 21:48 7679W3C_School 在线教程chm 版制作教程 ... -
String与StringBuffer区别详解
2010-12-17 17:19 3317String 与StringBuffe ... -
Spring 3.0 新特性
2010-12-10 10:58 3421Spring 3.0 新特性 ... -
iText生成PDF时表头设置错误导出数据不能完全导出
2010-07-20 12:16 2192在利用iText生成PDF文件时,通常由于数据量比较多时会产生 ... -
JavaMail
2009-07-16 16:56 0javamail 怎样设置发件人的名字 http://to ... -
IBM Ajax系列教程
2009-02-16 20:39 1741第 1 部分: Ajax 简介 Ajax ... -
项目经验之弹出页面再弹出页面
2009-02-13 18:58 1116在项目中有这样一个场景,某弹出页面要弹出另一个: 弹出页面: ... -
正则表达式使用之替换多个字符串
2009-02-13 15:44 2570想一次性去掉某个文本文件中的某些字符串: 实现方式: 直接用竖 ... -
OGNL的jar档、文档和源代码
2009-02-05 09:25 52261、官方网站: http://mirrors.ibiblio. ... -
Calendar与java.sql.Date
2008-12-08 15:29 1711在Oracle数据库中,我们会有Date类型的数据,存储格 ... -
利用JavaScript控制单选框
2008-12-04 19:14 2314<script> function f(index ... -
JSP中使用JavaScript重定向页面
2008-12-03 10:04 3366第一种,不重定向,推荐使用。 function init( ... -
如何去掉 Code Pro 的警告标志
2008-11-07 16:35 1345Code Pro 是一个很好的代码格式检查工具,不过有时我们只 ... -
使用Struts提交多行数据
2008-11-07 11:27 3925使用Struts提交多行数据 http://blog.fl ... -
Ant使用经验
2008-10-22 10:18 12981、【示例1】: <?xml version=" ... -
利用JXL(JExcelApi)操作Excel文档
2008-10-09 10:51 52641、工具类: package com.coderdream. ... -
JSP下载文档
2008-10-07 14:08 19271、设置doc格式的文件弹出对话框: <?xml v ...
相关推荐
本案例重点探讨了Spring如何与两种流行的数据访问技术——JDBC(Java Database Connectivity)和Hibernate——相结合,进行事务管理。事务控制是确保数据库操作一致性、完整性的关键,尤其在多步骤操作中,它能防止...
2. **Transaction Management**: Spring-JDBC支持声明式事务管理,允许开发者使用注解(如@Transactional)来控制事务的边界,无需手动调用commit()和rollback()。这提高了代码的可读性和可维护性。 3. **...
两个项目,一个项目是基于spring jdbc实现的分布式事务,一个是基于spring hibernate的分布式事务,hibernate项目里的applicationContext2.xml是基于mysql和mssql, applicationContext3.xml基于两个mssql, ...
Spring提供了两种事务管理方式:编程式事务管理和声明式事务管理。其中,声明式事务管理通过注解或者XML配置实现,更为简洁且易于维护。 Hibernate是一个流行的Java ORM(对象关系映射)框架,它简化了数据库操作,...
2. **Hibernate事务**: Hibernate本身也提供了一种事务管理机制,但在Spring环境中,我们通常使用Spring的事务管理器来协调。当@Transactional注解应用于方法上,Spring会在该方法执行前后自动管理事务的开始和结束...
在Java Web开发中,SSH(Spring、Struts、Hibernate)框架是常见的选择,它们提供了强大的功能,用于构建高效、可维护的应用程序。本资源“hibernate+junit+mysql-jdbc开发核心jar包三合一”显然是为了支持SSH框架中...
2. **事务管理**: Spring Boot默认使用`@Transactional`注解进行声明式事务管理。在需要事务操作的方法上添加该注解,Spring会自动管理事务的开始、提交或回滚。 3. **日志**: 开启SQL日志,有助于调试和性能优化。...
2. 声明式事务管理:利用@Transactional注解在方法级别声明事务,Spring会自动进行事务的开启、提交或回滚。 五、Spring JDBC与其他技术结合 1. MyBatis集成:Spring JDBC与MyBatis结合,可以利用MyBatis的动态SQL...
本篇将详细介绍如何在Spring 3和Hibernate 4中通过注解来实现声明式事务管理。 首先,我们需要在项目中引入Spring和Hibernate的依赖库。这通常通过Maven或Gradle等构建工具完成,确保添加了相应的依赖项。 接着,...
本篇将详细介绍如何在Spring 3和Hibernate 4中配置声明式事务管理,采用注解方式。 一、Spring的事务管理 Spring提供了两种事务管理方式:编程式事务管理和声明式事务管理。编程式事务管理需要在代码中显式地调用...
总之,这个示例将指导开发者如何将Spring MVC、JPA和Hibernate整合到同一个项目中,实现一个功能完善的Web应用,同时提供了一种组织和管理代码的方式。通过理解这些组件的协同工作,开发者可以更好地掌握Java Web...
在Java应用中,Spring框架提供了一种声明式事务管理方式,它允许开发者通过在方法级别上添加注解来定义事务边界。 Spring3引入了`@Transactional`注解,这是声明式事务管理的核心。当这个注解应用于一个方法时,...
它们各自负责不同的职责:Struts2用于控制应用程序的流程,Hibernate3则是优秀的对象关系映射(ORM)框架,Spring则提供全面的依赖注入(DI)和面向切面编程(AOP)功能,以及事务管理等企业级服务。将这三个框架...
1. 配置事务管理器:在Spring的XML配置文件中,根据数据库类型(如JDBC、Hibernate、MyBatis等)配置相应的事务管理器。 2. 开启事务:使用`@Transactional`注解标记需要在事务中执行的方法。 3. 业务逻辑:在事务中...
Spring 3.0 提供了两种事务管理配置方法:基于 XML 的事务管理和基于 @Transactional 的事务管理,这两种方法都是为了实现事务管理的目标,分别具有不同的配置方式和优缺点。 基于 XML 的事务管理 这种方法不需要...
5. **事务管理**:Spring JDBC模块与Spring的事务管理相集成,可以方便地进行编程式或声明式事务控制。例如,使用`TransactionTemplate`或在配置中定义@Transactional注解,可以实现事务的自动回滚和提交。 6. **...
- **易用性**:Hibernate通过面向对象的方式管理事务,相比JDBC的SQL操作,更易于理解和实现。 - **效率**:JDBC直接操作数据库,通常比Hibernate的ORM操作更快,但在事务管理上可能需要更多代码。 - **灵活性**:...
2. **事务管理**:Spring提供了声明式和编程式两种事务管理方式。声明式事务管理通过在服务层方法上添加@Transactional注解,让Spring自动处理事务的开始、提交或回滚。编程式事务管理则需要在代码中手动调用...
### 基于注解的Spring MVC+Hibernate简单入门 #### 概述 本文主要介绍如何使用基于注解的方式构建Spring MVC与Hibernate相结合的应用程序。这种方式不仅简化了配置过程,而且提高了开发效率。我们将通过一个具体的...
Spring支持两种类型的事务管理方式:编程式事务管理和声明式事务管理。 #### 二、编程式事务管理 编程式事务管理允许开发人员通过编程的方式直接控制事务的开始、提交或回滚。这种方式相对灵活,但也存在一些缺点...