【Spring实战】—— 16 基于JDBC持久化的事务管理
前面讲解了基于JDBC驱动的Spring的持久化管理,本篇开始则着重介绍下与事务相关的操作。
通过本文你可以了解到:
1 Spring 事务管理的机制
2 基于JDBC持久化的事务管理
Spring的事务管理的机制
Spring本身并不提供事务管理,它只是把事务管理提交给事务管理器,而事务管理器则有多种实现,常见的就是基于JDBC的、Hibernate的、JPA以及JTA的。
操作流程可以参考下面的图片:
其实还有好多种类的事务管理器,这里就不一一列举了。
基于JDBC持久化的事务管理
基于JDBC的持久化,其实就是使用JDBC驱动,在利用spring模板的情况下实现的持久化。
与Hibernate不同的是,它没有一些Session的概念以及实体关联关系等,因此在查询结果的时候,需要手动的进行转换。
其他的方面来说,还是很简单实用的。
下面看一下主要的代码实现流程:
观察上面的实现结构,整个代码在DAO层的实现部分编写,其中包括主要的两个bean,一个是Spring的JDBC模板,一个是事务处理,这两个bean都会依赖于dataSource。
DAO(data access object)数据访问对象,一般应用架构都会设计这样一层,用于存放于数据库进行交互的代码,以使应用层次化,便于管理和开发。
因此就好理解下面的配置文件了:
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- JDBC数据源配置 -->
<bean id="dataSource" 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="root"/>
<property name="password" value="123qwe"/>
</bean>
<!-- 配置DAO实现类,注入jdbcTemplate和transactionManager -->
<bean id="newjdbcdao" class="com.spring.chap6.dao.NewJdbcImpl" >
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="transactionManager" ref="transactionManager"/>
</bean>
<!-- 将数据源注入到jdbctemplate中 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 将数据源注入到transactionManager中 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
下面是dao的接口部分,仅仅给出了查询所有数据和插入一条数据的例子:
public interface NewJdbc {
//插入数据
public void insertPerson(String id,String name,int age);
//通过ID查询数据
public void findAllPersons();
}
下面是重要的部分,查询方法,仅仅通过模板提供了一个模板的使用样例。
其中query方法含有两个参数。
一个是查询SQL语句,另一个是转换类(用于把查询结果ResultSet转换成POJO类)。
而插入数据的方法中,使用了事务管理。
当执行new Integer("hello!")时,由于字符串无法转换到整型出错,会导致事务回滚,写操作回滚。
其中的事务处理的源码参考如下,还没看明白,日后慢慢学习:
源码给出,仅供参考:
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Error err) {
// Transactional code threw error -> rollback
rollbackOnException(status, err);
throw err;
}
catch (Exception ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
下面则是DAO的实现部分的所有代码:
public class NewJdbcImpl extends JdbcDaoSupport implements NewJdbc{
public DataSourceTransactionManager transactionManager;
public void setTransactionManager(DataSourceTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* 插入数据
*/
public void insertPerson(final String id,final String name,final int age){
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
final JdbcTemplate jdbcTemplate = this.getJdbcTemplate();
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
//这个方法内部,是一个事务
jdbcTemplate.update("insert into persons(id,name,age) values (?,?,?)",
id,name,age);
new Integer("hello!");
}
});
}
/**
* 查询所有的数据
*/
public void findAllPersons(){
List<Person> list = this.getJdbcTemplate().query("select * from persons", new PersonRowMapper());
for(Person p : list){
System.out.println("id:"+p.getId()+" name:"+p.getName()+" age:"+p.getAge());
}
}
/**
* 转换查询结果
* @author xingoo
*/
class PersonRowMapper implements RowMapper{
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Person person = new Person();
person.setId(rs.getString(1));
person.setName(rs.getString(2));
person.setAge(rs.getInt(3));
return person;
}
}
}
Person的POJO类:
public class Person {
private String id;
private String name;
private int age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试时使用的main方法(一直没有使用单元测试,真不专业,习惯下次要改!)
public class test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
NewJdbc newjdbc = (NewJdbc)ctx.getBean("newjdbcdao");
newjdbc.insertPerson("005", "xingoo5", 25);
newjdbc.findAllPersons();
}
}
数据库的SQL部分可以参考前一篇。
【这里遗留了一个问题,当事务失败回滚时,查询语句也无法执行了。难道是因为使用的同一个JdbcTempalte的缘故?这个问题需要看源码探究,暂时记录一下。】
1 根据网上搜索的资料:
根据默认规则,如果在执行回调方法的过程中抛出了未检查异常,或者显式调用了TransacationStatus.setRollbackOnly() 方法,则回滚事务;如果事务执行完成或者抛出了 checked 类型的异常,则提交事务。
但是回滚事务,为什么程序直接停止了呢。
参考
[1] Spring JDBC事务管理
[2] 《Spring in Action》
【Spring实战】—— 16 基于JDBC持久化的事务管理的更多相关文章
- Spring Boot 中使用 @Transactional 注解配置事务管理
事务管理是应用系统开发中必不可少的一部分.Spring 为事务管理提供了丰富的功能支持.Spring 事务管理分为编程式和声明式的两种方式.编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP ...
- Spring Boot中使用@Transactional注解配置事务管理
事务管理是应用系统开发中必不可少的一部分.Spring 为事务管理提供了丰富的功能支持.Spring 事务管理分为编程式和声明式的两种方式.编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP ...
- 谈谈分布式事务之二:基于DTC的分布式事务管理模型[下篇]
[续上篇] 当基于LTM或者KTM的事务提升到基于DTC的分布式事务后,DTC成为了本机所有事务型资源管理器的管理者:此外,当一个事务型操作超出了本机的范 围,出现了跨机器的调用后,本机的DTC需要于 ...
- 创建JDBC模板简化代码、JDBC应用的事务管理以及连接池的作用
一.创建JDBC模板简化代码 一个简单的查询.要做这么一大堆事情,并且还要处理异常,我们不防来梳理一下: 1.获取connection 2.获取statement 3.获取resultset 4 ...
- Spring整合Hibernate 二 - 声明式的事务管理
Spring大战Hibernate之声明式的事务管理 Spring配置文件: 添加事务管理类的bean: <bean id="txManager" class="o ...
- Spring Boot 2.x基础教程:事务管理入门
什么是事务? 我们在开发企业应用时,通常业务人员的一个操作实际上是对数据库读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻 ...
- 四、spring的JDBC模板和事务管理
Spring的JDBC模板 Spring是JavaEE开发的一站式框架,对各种持久化技术都提供了简单的模板 ORM持久化技术 模板类 JDBC org.springframework.jdbc.cor ...
- java框架之Spring(3)-JDBC模板使用&事务管理
下面内容使用到的 jar 包下载 JDBC模板使用 入门 1.导包,如要导入 Spring 的基本开发包.数据库驱动包.Spring 提供的 JDBC 模板包,如下: 2.测试: @Test publ ...
- JAVA JDBC(存储过程和事务管理)
1.什么是存储过程 存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程 ...
随机推荐
- Carryon 数数字
Carryon 数数字 描述 Carryon 最近迷上了数数字,然后 Starry 给了他一个区间[l,r] ,然后提了几个要求, 需要将 l 到 r 之间的数全部转化成 16 进制,然后连起来. 将 ...
- Selenium => Debugging “Element is not clickable at point” error
[From] http://stackoverflow.com/questions/11908249/debugging-element-is-not-clickable-at-point-error ...
- drf序列化器的实例
应用目录结构: views.py from django.shortcuts import render # Create your views here. from django.views imp ...
- firewall-cmd --reload 防火墙
防火墙重新加载配置firewall-cmd --reload 查看开放的端口 firewall-cmd --list-ports nano /etc/sysconfig/iptables -A IN_ ...
- MongoDB复杂查询语句记录
前段时间做业务监控,用到了MongoDB,有一个查询是把一个含array的list里面查询array中是否存在某一对unique值,不存在的情况下插入一条记录. 类似这样一个表: Biao{ id, ...
- 基于setTimeout制作滚动广告板
很多网站在其门户页面的上方正中央都会放置一个滚动广告板,用于显示一些推荐信息,用户点击即可进入浏览.比较常见的就是各个公司的官网,电商网站的首页等. 下面是天猫的滚动广告板截图. 其实,不需要借助于什 ...
- java中的各种修饰符作用范围
访问修饰符: private 缺省 protected public 作用范围: 访问修饰符\作用范围 所在类 同一包内其他类 其他包内子类 其他包内非子类 private 可以访问 不可以 不可以 ...
- [转]NLog Layout Renderers ${}
https://github.com/nlog/NLog/wiki/Layout-Renderers Layout renderers are template macros that are use ...
- SQL动态配置,动态解析SQL
在项目中使用SQL动态配置的方式可以让后期的维护和发布后的修改变得更加方便,无论使用那种配置方式都离不开解析成最终真正能执行的SQL.下面代码就是一种比较简单的处理方法,SQL的参数以##括起来. 1 ...
- ASP.NET内置对象-网页转向的4中方法
ASP.NET页面跳转的方法 1.超链接 2.Response.Redirect(“Urlstring”) 3.Server.Transfer(“UrlString”) 4.PostBackUrl 1 ...