Spring事务管理器JDBC的实现
2016-12-09 20:48
936 查看
Spring事务管理的实现有许多细节,如果对整个接口框架有个大体了解会非常有利于我们理解事务,下面通过Spring的事务接口来了解Spring实现事务的具体策略。
Spring事务管理涉及的接口的联系如下:
Spring声明式事务管理器类:
Jdbc技术:DataSourceTransactionManager
Hibernate技术:HibernateTransactionManager
Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。此接口的内容如下:
从这里可知具体的具体的事务管理机制对Spring来说是透明的,它并不关心那些,那些是对应各个平台需要关心的,所以Spring事务管理的一个优点就是为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、JPA。下面分别介绍各个平台框架实现事务管理的机制。
实际上,DataSourceTransactionManager是通过调用java.sql.Connection来管理事务,而后者是通过DataSource获取到的。通过调用连接的commit()方法来提交事务,同样,事务失败则通过调用rollback()方法进行回滚。
例子
package spring.mybatis.transaction;
public class Account {
private String user;
private int balance;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
}
DAO具体实现类。此时并没有合并MyBatis。所以不是借口,还是类。但需要注意的是。这里的映射关系实现是通过RowMapper<Account>()这个匿名类实现的。
实现类
Spring事务管理涉及的接口的联系如下:
Spring声明式事务管理器类:
Jdbc技术:DataSourceTransactionManager
Hibernate技术:HibernateTransactionManager
事务管理器
Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。此接口的内容如下:
Public interface PlatformTransactionManager()...{ // 由TransactionDefinition得到TransactionStatus对象 TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; // 提交 Void commit(TransactionStatus status) throws TransactionException; // 回滚 Void rollback(TransactionStatus status) throws TransactionException; }
从这里可知具体的具体的事务管理机制对Spring来说是透明的,它并不关心那些,那些是对应各个平台需要关心的,所以Spring事务管理的一个优点就是为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、JPA。下面分别介绍各个平台框架实现事务管理的机制。
JDBC事务
如果应用程序中直接使用JDBC来进行持久化,DataSourceTransactionManager会为你处理事务边界。为了使用DataSourceTransactionManager,你需要使用如下的XML将其装配到应用程序的上下文定义中:<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
实际上,DataSourceTransactionManager是通过调用java.sql.Connection来管理事务,而后者是通过DataSource获取到的。通过调用连接的commit()方法来提交事务,同样,事务失败则通过调用rollback()方法进行回滚。
注解方式声明事务
开启注解扫描<!--事务管理器类--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--开启注解扫描--> <context:component-scan base-package="com.juaner.spring.tx"/> <!--注解方式实现事务--> <tx:annotation-driven transaction-manager="txManager"/>
例子
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd "> <!-- 这一行是让他自动扫描注册spring bean --> <context:component-scan base-package="spring.mybatis.transaction"> </context:component-scan> <tx:annotation-driven transaction-manager="txManager"/> <!-- 这一行是基于注解实现事务管理器 下面这个是具体的jdbc的事务管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test" /> <property name="username" value="root" /> <property name="password" value="123" /><!-- 其实这些参数也可以直接写值,不用.properties文件也行 --> </bean> </beans>简单JAV类(POJO)
package spring.mybatis.transaction;
public class Account {
private String user;
private int balance;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
}
DAO具体实现类。此时并没有合并MyBatis。所以不是借口,还是类。但需要注意的是。这里的映射关系实现是通过RowMapper<Account>()这个匿名类实现的。
package spring.mybatis.transaction; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Repository public class AccountDao { private JdbcTemplate jdbcTemplate;//此处是同过Spring JDBC 连接数据库。不是mybatis。 @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public void resetMoney() { jdbcTemplate.update("update account set balance=1000"); } public List<Account> accountList() { return this.jdbcTemplate.query("select * from account", new RowMapper<Account>() { // 消除警告的是靠 // new RowMapper<Account>的泛型 //里RowMapper可以将数据中的每一行数据封装成用户定义的类。当有了mybatis后就不用这样了。mybatis会将查询结果映射成就扣对象 //sping中的RowMapper可以将数据中的每一行数据封装成用户定义的类。 public Account mapRow(ResultSet rs, int rowNum) throws SQLException { // TODO Auto-generated method stub Account account = new Account(); account.setUser(rs.getString("user")); account.setBalance(rs.getInt("balance")); return account; } }); } // 下面这个就是事物 @Transactional(propagation=Propagation.REQUIRED) public void transforMoney(String source, String target, double count) { this.jdbcTemplate.update("update account set balance=balance-? where user=?", count, source); // 下面故意加入错误,使事物中断 throwException(); this.jdbcTemplate.update("update account set balance=balance+? where user=?", count, target); } private void throwException() { throw new RuntimeException("ERROR"); } }
实现类
package spring.mybatis.transaction; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import spring.jdbc.JdbcTemplateDao; public class TestData { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("springmybatistransaction.xml"); AccountDao dao=ctx.getBean("accountDao", AccountDao.class); dao.resetMoney(); /* * 这里给dao.transforMoney加try catch 是为了让即使出错也能打印出来余额。。? */ try{ dao.transforMoney(" LiLei", " HaiMeiMei", 521); }catch(Exception e){ System.out.println(e.getMessage()); } List<Account> accountList =dao.accountList(); for(Account account:accountList){ System.out.println(account.getUser()+account.getBalance()); } } }
相关文章推荐
- 如何实现win9X进程间数据通讯技术
- 用canvas实现红心飘飘的动画效果
- 利用Hook技术实现键盘监控
- 用Delphi实现远程屏幕抓取
- 如何利用C++ Builder 4.0 Enterprise实现对Excel97 的调用
- 应用程序敏感键的实现
- 在PB中快速实现数据库树形结构
- 在PowerBuilder中实现菜单条级权限的设置
- PB7.0中实现Jaguar GTS组件开发
- 如何实现数据的自动录入
- PowerBuilder中实现数据窗口打印预览通用方法
- 用Delphi实现远程屏幕抓取
- 用CTI实现与Web交谈
- WebClass实现动态WEB编程之理论篇
- WebClass实现动态WEB编程之实践篇
- 实现类似IE的打印网页功能
- 用DELPHI实现特色按钮
- 串行通信的基本原理及用MFC实现串口通信编程
- 如何在应用程序中实现关机功能
- 用Delphi在工业控制和自动化实现多线程进行数据采集