第三十 访问财富进退自如 —Spring交易管理
6月16日本,明确。
“应该留给追穷寇勇,不可沽名学霸王。天若有情天亦老,人间正道是沧桑。”
有始有终、有往有还、进退自如乃Spring事务管理之道,也是万物生生不息、和谐共处之道。
遵道而行。但到半途需努力。会心不远,欲登绝顶莫辞劳。
数据库的更新通常都是由客观世界的所发生的事件引起的。
为保证数据库内容的一致,就要将数据库的一组操作作为一个总体来进行。要么所有成功完毕。要么所有失败退出。
假设因为故障或其他原因而使一组操作中有一些完毕。有一些未完毕。则必定会使得数据库中的数据出现不一致,从而使得数据库的完整性受到破坏。因此,更新操作序列必须作为一个总体在DBMS运行时出现。即“要么全做,要么全不做”。SQL提供了事务处理的机制,来帮助DBMS实现上述的功能。
一、以下看一个单纯的spring的声明式(XML 式)事务管理的样例。
1、创建MySQL数据库
见 第十九天 慵懒的投射在JDBC上的暖阳 —Hibernate的使用(一)
由于要演示数据回滚。须要把MySQL默认的ENGINE = MyISAM改为ENGINE =InnoDB。目的是让数据库支持回滚。
怎样改动,最简单的做法,就是使用Navicat这个工具,设计表—>选项—>表类型
2、创建DAO接口
package edu.eurasia.dao;public interface TmDao {public void insert();public void select();
}
3、创建DAO的实现类
package edu.eurasia.dao;import java.util.List;import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;public class TmDaoImpl extends JdbcDaoSupport implements TmDao {public void insert() {try {super.getJdbcTemplate().update("update userinfo set username = '唐伯虎' where id =2");super.getJdbcTemplate().update("INSERT INTO userinfo(username,password) VALUES('李苦禅','88888888')");super.getJdbcTemplate().update("DELETE FROM userinfo where id =2");} catch (Exception e) {logger.error("小心地雷!
" + e.getMessage()); e.printStackTrace(); throw new RuntimeException(); // 假设凝视掉throw new RuntimeException。那么事务将不能回滚。由于spring捕捉不到Exception } } public void select() { List list = super.getJdbcTemplate().query("select * from userinfo", new ColumnMapRowMapper()); System.out.println(list); } }
4、创建service接口
package edu.eurasia.service;public interface TmService {public void insert();public void select();
}
5、实现service接口
package edu.eurasia.service;import edu.eurasia.dao.TmDao;public class TmServiceImpl implements TmService {private TmDao tmDao;public TmDao getTmDao() {return tmDao;}public void setTmDao(TmDao tmDao) {this.tmDao = tmDao;}@Overridepublic void insert() {tmDao.insert(); }@Overridepublic void select() {tmDao.select();}
}
6、编写spring的配置文件applicationContext.xml
<?
xml version="1.0" encoding="UTF-8"?
> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <!-- 数据源 配置--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/hib?
useUnicode=true&characterEncoding=UTF-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </bean> <!-- 事务管理器 注入dataSource --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- spring提供的操作数据库用的句柄,相似JDBC的Statement类 ,bean能够不写--> <!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> --> <!-- 本例中继承了JdbcDaoSupport的父类。它里面有"jdbcTemplate"和"dataSource"的set接口,仅仅需注入随意一个即可了 --> <bean id="tmDao" class="edu.eurasia.dao.TmDaoImpl"> <!-- <property name="jdbcTemplate" ref="jdbcTemplate" /> --> <property name="dataSource" ref="dataSource" /> </bean> <!-- Service配置 --> <bean id="tmService" class="edu.eurasia.service.TmServiceImpl"> <property name="tmDao" ref="tmDao"></property> </bean> <!-- 通知器: name="*"是表示切入目标类的全部方法,即TmDao类的全部方法,REQUIRED的意思是在同个方法类的全部sql操作在同一个进程中,这样才干实现回滚操作,dao类里抛出的Exception,所以要求的是凡是发生Exception就回滚--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" /> </tx:attributes> </tx:advice> <!-- 切面配置:第一个*表示返回类型,edu.eurasia.dao.表示edu.eurasia.dao包及其他的子包的类,第二个*表示类中的全部方法名,(..)表示随意类型,随意个数的參数 --> <aop:config> <aop:pointcut id="pointcut" expression="execution(* edu.eurasia.dao.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config> </beans>
7、编写測试类TestTm.java
package edu.eurasia.test;import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import edu.eurasia.service.TmService;public class TestTm {static Logger logger = Logger.getLogger(TestTm.class);@Testpublic void tsettm() {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");TmService tmservice = (TmService) context.getBean("tmService");tmservice.insert();tmservice.select();}
}
8、执行结果分析
Spring的事务管理默认仅仅对出现执行期异常(java.lang.RuntimeException及其子类)进行回滚。 假设一个方法抛出Exception或者Checked异常。Spring事务管理默认不进行回滚。
所以。DAO的实现类TmDaoImpl.java中要catch RuntimeException()异常。
仅仅抛出普通exception的话,不会回滚。有的童鞋按上面代码进行測试。发现没有回滚。数据库正常插入一条数据。原因是程序没有异常,须要人为制造一个,比方改动SQL语句"DELETE FROM userinfo where id1 =2" ,把字段id 改成id1,再试一试,观察控制台你会发现:com.mysql.jdbc.exceptions.MySQLSyntaxErrorException异常抛出。
还有例如以下内容:
log4j.properties的编写见第二十八天 月出惊山鸟 —Spring的AOP
DEBUG [main] (AbstractPlatformTransactionManager.java:821) - Initiating transaction rollback
DEBUG [main] (DataSourceTransactionManager.java:273) - Rolling back JDBC transaction on Connection [com.mysql.jdbc.Connection@9283b0]
再刷新数据库。也不会新插入一条数据。
回滚成功!
注意:像删除或更新一条不存在的记录,类似这些操作,程序是不报异常的,自然不会回滚。能够依据须要自己定义异常。让自己定义的异常继承自RuntimeException。这样抛出的时候才会被Spring默认的事务处理准确处理。
9、环境配置
本例使用spring 2.5.6。除了找出spring.jar,commons-logging-1.1.1.jar两个jar包。外加一个log4j.jar。
还要下载aspectjweaver.jar。
别忘了mysql-connector-java-5.0.8-bin.jar。
项目结构如图:
二、用注解实现事务管理
使用注解来实现声明式事务,这种方法简洁方便。把上面的样例稍加修改就可以。
1、改动配置文件applicationContext.xml,将全部具有@Transactional 注解的bean自己主动配置为声明式事务支持。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"><!-- 数据源 配置--><bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"destroy-method="close"><property name="driverClassName" value="com.mysql.jdbc.Driver" /><property name="url"value="jdbc:mysql://localhost:3306/hib?useUnicode=true&characterEncoding=UTF-8" /><property name="username" value="root" /><property name="password" value="root" /> </bean><!-- 事务管理器 注入dataSource --><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /> </bean><!-- spring提供的操作数据库用的句柄,相似JDBC的Statement类 ,bean能够不写--><!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean> --><!-- 本例中继承了JdbcDaoSupport的父类。它里面有"jdbcTemplate"和"dataSource"的set接口,仅仅需注入随意一个即可了 --><bean id="tmDao" class="edu.eurasia.dao.TmDaoImpl"><!-- <property name="jdbcTemplate" ref="jdbcTemplate" /> --><property name="dataSource" ref="dataSource" /></bean><!-- Service配置 --><bean id="tmService" class="edu.eurasia.service.TmServiceImpl"><property name="tmDao" ref="tmDao"></property> </bean><!-- 用 注解来实现事务管理 --> <tx:annotation-driven transaction-manager="transactionManager" />
</beans>
2、在接口或类的声明处 ,写一个@Transactional。要是仅仅的接口上写, 接口的实现类就会继承下来。
接口的实现类的详细方法,还能够覆盖类声明处的设置。
改动DAO的实现类。加上注解就可以。
package edu.eurasia.dao;import java.util.List;import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Transactional
public class TmDaoImpl extends JdbcDaoSupport implements TmDao {@Transactional(propagation=Propagation.REQUIRED,rollbackFor={Exception.class}) public void insert() {try {super.getJdbcTemplate().update("update userinfo set username = '唐伯虎' where id =3");super.getJdbcTemplate().update("INSERT INTO userinfo(username,password) VALUES('李苦禅','88888888')");super.getJdbcTemplate().update("DELETE FROM userinfo where id =4");} catch (Exception e) {logger.error("小心地雷!
" + e.getMessage()); e.printStackTrace(); throw new RuntimeException(); // 假设凝视掉throw new RuntimeException,那么事务将不能回滚,由于spring捕捉不到Exception } } public void select() { List list = super.getJdbcTemplate().query("select * from userinfo", new ColumnMapRowMapper()); System.out.println(list); } }
执行效果和上面的样例是一致的。
版权声明:本文博客原创文章。博客,未经同意,不得转载。
转载于:https://www.cnblogs.com/bhlsheji/p/4688949.html
第三十 访问财富进退自如 —Spring交易管理相关推荐
- Spring Security(三十六):12. Spring MVC Test Integration
Spring Security provides comprehensive integration with Spring MVC Test Spring Security提供与Spring MVC ...
- Expo大作战(三十)--expo sdk api之Permissions(权限管理模块),Pedometer(计步器api)
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- 精选Spring Boot三十五道必知必会知识点!
Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家.本文精选了三十五个常见的Spring Boot知识点,祝你一臂之力! 问题一 Spr ...
- SpringBoot:三十五道SpringBoot面试题及答案!
SpringBoot面试 前言 今天博主将为大家分享三十五道SpringBoot面试题及答案,不喜勿喷,如有异议欢迎讨论! Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成 ...
- spring boot 入门_SpringBoot入门建站全系列(三十)Mybatis多数据源进行数据库操作
SpringBoot入门建站全系列(三十)Mybatis多数据源进行数据库操作 一.概述 多数据源,就是有多个数据库的配置. 多数据源配置并不麻烦,使用起来和单数据源基本相同,但是,重要的是事务的控制 ...
- spring boot+iview 前后端分离架构之用户管理的实现(三十)
spring boot 与 iview 前后端分离架构之用户管理的实现(三十) 公众号 用户管理 相关工具类的实现 User实体改造 UserOrg实体改造 UserRole实体改造 UserRole ...
- spring boot 与 iview 前后端分离架构之开发环境基于docker的部署的实现(三十六)
spring boot 与 iview 前后端分离架构之开发环境基于docker的后端的部署的实现(三十六) 公众号 基于docker的后端的部署 安装mysql数据库 创建数据库 安装redis 安 ...
- 中国海军第三十批护航编队结束访问菲律宾启程回国
当地时间1月21日,东平湖舰离开马尼拉港. 来永雷 摄 当地时间1月21日,东平湖舰离开马尼拉港. 来永雷 摄 当地时间1月21日,邯郸舰离开马尼拉港. 来永雷 摄 中新网马尼拉1月22日电 (张海龙 ...
- 第四名:王永庆家族 中国十大财富家族史
2006.9.2 07:25 中国十大财富家族史:王永庆 第四名:王永庆家族 6月5日,台塑集团在股东大会结束后宣布了自企业成立以来最重大的一次人事变动.担任台塑集团董事长达半个世纪之久的王永庆卸任, ...
- 投资高手三十年投资经验总结的18条真谛
本书作者冯时能是马来西亚南洋商报总编,和香港信报编辑曹仁超类似,都有差不多30多年的投资经验,且几乎完全依靠个人力量在投资上获得了财务自由.尽管没有确切信息表明冯先生的实际投资回报,但考虑到在马来西亚 ...
最新文章
- ORM 一对一 以及csrf 的简单用法
- Across the universe
- XCTF-高手进阶区:ics-07
- LeetCode 329. 矩阵中的最长递增路径(记忆化递归)
- web字体设置成平方字体_如何托管自己的Web字体
- SAP License:ERP横向集中部署还是纵向集中部署
- SQL的几种连接查询方式(内连接、外连接、全连接、联合查询)
- 图解机器学习算法(9) | GBDT模型详解(机器学习通关指南·完结)
- 斑马网络招聘汽车安全软件工程师
- 为什么谷歌浏览器打不开 Google Chrome打不开解决方法
- 中印程序员对比:是什么让我们觉得印度程序员很厉害?
- bzoj4816: [Sdoi2017]数字表格
- 反思:为什么你做淘宝客不赚钱
- Mac上怎么把mov文件转成gif文件
- Ubuntu18.04 ROS Melodic版本安装gazebo_ros_pkgs包
- python 妹子图抓取
- 深度学习平台、CPU和GPU使用
- Vue中使用Font Awesome
- 移动端二三事【五】:陀螺仪(重力感应器)实现手机位置、加速度感应以及常见应用。
- md5碰撞Java_2 MD5加密 java实现