Java EE学习笔记(五)
Spring事务管理
1、Spring事务管理概述
1)、在实际开发中,操作数据库时都会涉及到事务管理问题,为此Spring提供了专门用于事务处理的API。(事务特性:ACID,原子性,一致性,隔离性,持久性)
2)、事务管理的核心接口:在Spring的所有JAR包中,包含一个名为spring-tx-4.3.6.RELEASE的JAR包,该包就是Spring提供的用于事务管理的依赖包。在该JAR包的org.springframework.transaction包中,有3个接口文件PlatformTransactionManager、TransactionDefinition和TransactionStatus,如下图所示:
3)、Platform TransactionManager接口
a)、PlatformTransactionManager接口是Spring提供的平台事务管理器,主要用于管理事务。该接口中提供了三个事务操作的方法,具体如下:
用于获取事务状态信息:TransactionStatus getTransaction(TransactionDefinition definition);
用于提交事务:void commit(TransactionStatus status);
用于回滚事务:void rollback(TransactionStatus status);
b)、PlatformTransactionManager接口只是代表事务管理的接口,并不知道底层是如何管理事务的,具体如何管理事务则由它的实现类来完成。该接口常见的几个实现类如下:
1、用于配置JDBC数据源的事务管理器:
org.springframework.jdbc.datasource.DataSourceTransactionManager
2、用于配置Hibernate的事务管理器:
org.springframework.orm.hibernate4.HibernateTransactionManager
3、用于配置全局事务管理器:
org.springframework.transaction.jta.JtaTransactionManager
当底层采用不同的持久层技术时,系统只需使用不同的PlatformTransactionManager实现类即可。
4)、TransactionDefinition接口
a)、TransactionDefinition接口是事务定义(描述)的对象,该对象中定义了事务规则(事物详情),并提供了获取事务相关信息的方法,具体如下:
1、获取事务对象名称:String getName( );
2、获取事务的隔离级别:int getIsolationLevel( );
3、获取事务的传播行为:int getPropagationBehavior( );
4、获取事务的超时时间:int getTimeout( );
5、获取事务是否只读:boolean isReadOnly( );
上述方法中,事务的传播行为是指在同一个方法中,不同操作前后所使用的事务。传播行为有很多种,具体如下表所示:
在事务管理过程中,传播行为可以控制是否需要创建事务以及如何创建事务,通常情况下,数据的查询不会影响原数据的改变,所以不需要进行事务管理,而对于数据的插入、更新和删除操作,必须进行事务管理。如果没有指定事务的传播行为,Spring默认传播行为是REQUIRED(required)。
5)、TransactionStatus接口
a)、TransactionStatus接口是事务的状态,它描述了某一时间点上事务的状态信息。该接口中包含6个方法,具体如下:
1、刷新事务:void flush();
2、获取是否存在保存点:boolean hasSavepoint();
3、获取事务是否完成:boolean isCompleted();
4、获取是否为新事务:boolean isNewTransaction();
5、获取事务是否回滚:boolean isRollbackOnly();
6、设置事务回滚:void setRollbackOnly();
6)、事务管理的方式:
声明式事务管理最大的优点在于开发者无需通过编程的方式来管理事务,只需在配置文件中进行相关的事务规则声明,就可以将事务应用到业务逻辑中。
2、声明式事务管理
1)、Spring的声明式事务管理可以通过两种方式来实现,一种是基于XML的方式,另一种是基于Annotation的方式。
2)、基于XML方式的声明式事务:在配置文件中通过<tx:advice>元素配置事务规则来实现的。当配置了事务的增强处理后,就可以通过编写的AOP配置,让Spring自动对目标生成代理。<tx:advice>元素及其子元素如下图所示:
3)、配置<tx:advice>元素的重点是配置<tx:method>子元素,上图中使用灰色标注的几个属性是<tx:method>元素中的常用属性。其属性描述具体如下:
4)、src->com.itheima.jdbc
①普通用户类:Account.java
package com.itheima.jdbc;
public class Account { private Integer id; // 账户id
private String username; // 用户名
private Double balance; // 账户余额 public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public Double getBalance() {
return balance;
} public void setBalance(Double balance) {
this.balance = balance;
} public String toString() {
return "Account [id=" + id + ", "+ "username=" + username + ", balance=" + balance + "]";
}
}
②操作用户接口类:AccountDao.java
package com.itheima.jdbc; import java.util.List; public interface AccountDao { // 添加
public int addAccount(Account account); // 更新
public int updateAccount(Account account); // 删除
public int deleteAccount(int id); // 通过id查询
public Account findAccountById(int id); // 查询所有账户
public List<Account> findAllAccount(); // 添加一个转账方法
public void transfer(String outUser,String inUser,Double money);
}
③在AccountDaoImpl.java实现transfer()方法:
/**
* 转账
* inUser:收款人
* outUser:汇款人
* money:收款金额
*/
public void transfer(String outUser, String inUser, Double money) {
// 收款时,收款用户的余额=现有余额+所汇金额
this.jdbcTemplate.update("update account set balance = balance +? "
+ "where username = ?",money, inUser);
// 模拟系统运行时的突发性问题
int i = 1/0;
// 汇款时,汇款用户的余额=现有余额-所汇金额
this.jdbcTemplate.update("update account set balance = balance-? "
+ "where username = ?",money, outUser);
}
③配置文件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:aop="http://www.springframework.org/schema/aop"
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-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- 1、配置数据源 -->
<bean id="dataSourceID" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!--1.1、数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" /> <!--1.2、连接数据库的url(即数据库所在地址) -->
<property name="url" value="jdbc:mysql://localhost:3306/spring" /> <!--1.3、连接数据库的用户名 -->
<property name="username" value="root" /> <!--1.4、连接数据库的密码 -->
<property name="password" value="******" />
</bean> <!-- 2、配置JDBC模板,并且注入数据源 -->
<bean id="jdbcTemplateID" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 2.1、默认必须使用数据源 -->
<property name="dataSource" ref="dataSourceID" />
</bean> <!--3、定义id为accountDaoID的Bean,即配置DAO层-->
<bean id="accountDaoID" class="com.itheima.jdbc.AccountDaoImpl"> <!-- 3.1、将jdbcTemplate注入到accountDao类实例中 -->
<property name="jdbcTemplate" ref="jdbcTemplateID" />
</bean> <!-- 4、事务管理器,依赖于数据源(注入DataSource),事务从Connection获得,连接从连接池DataSource获得 -->
<bean id="transactionManagerID" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceID" />
</bean> <!-- 5、编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节
<tx:attributes>用于配置事务的属性
<tx:method name=""/>详情的具体配置
propagation:指定事务的传播行为,REQUIRED是必须的
isolation:指定事务的隔离级别
-->
<tx:advice id="txAdviceID" transaction-manager="transactionManagerID"> <tx:attributes>
<!-- 5.1、name:*表示任意方法名称 -->
<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false" />
</tx:attributes>
</tx:advice> <!-- 6.编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config> <!-- 6.1、切入点 -->
<aop:pointcut expression="execution(* com.itheima.jdbc.*.*(..))" id="txPointCutID" /> <!-- 6.2、切面:将切入点与通知整合 -->
<aop:advisor advice-ref="txAdviceID" pointcut-ref="txPointCutID" />
</aop:config>
</beans>
④交易测试类:TransactionTest.java
package com.itheima.jdbc;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
//测试类
public class TransactionTest { @Test
public void xmlTest(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // 1、获取AccountDao的Bean实例accountDaoID
AccountDao accountDao = (AccountDao)applicationContext.getBean("accountDaoID"); // 2、调用实例中的转账方法
accountDao.transfer("Jack", "Rose", 100.0); // 3、输出提示信息
System.out.println("转账成功!");
}
}
⑤运行结果:(异常/by zero报错,说明Spring中的事务管理配置已经生效)
5)、基于Annotation方式的声明式事务
a)、在Spring容器中注册事务注解驱动;
<tx:annotation-driven transaction-manager="transactionManager"/>
b)、在需要事务管理的类或方法上使用@Transactional注解。
如果将注解添加在Bean类上,则表示事务的设置对整个Bean类的所有方法都起作用;如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该方法有效。
c)、使用@Transactional注解时,可以通过参数配置事务详情:
d)src->applicationContext-annotation.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:aop="http://www.springframework.org/schema/aop"
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-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 1.配置数据源 -->
<bean id="dataSourceID" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!--数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" /> <!--连接数据库的url -->
<property name="url" value="jdbc:mysql://localhost/spring" /> <!--连接数据库的用户名 -->
<property name="username" value="root" /> <!--连接数据库的密码 -->
<property name="password" value="******" /> </bean>
<!-- 2.配置JDBC模板 -->
<bean id="jdbcTemplateID" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 默认必须使用数据源 -->
<property name="dataSource" ref="dataSourceID" /> </bean> <!--3.定义id为accountDao的Bean实例 -->
<bean id="accountDaoID" class="com.itheima.jdbc.AccountDaoImpl"> <!-- 将jdbcTemplate注入到AccountDao实例中 -->
<property name="jdbcTemplate" ref="jdbcTemplateID" />
</bean> <!-- 4.事务管理器,依赖于数据源 -->
<bean id="transactionManagerID" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceID" />
</bean> <!-- 5.注册事务管理器驱动,替换编写aop和编写通知 -->
<tx:annotation-driven transaction-manager="transactionManagerID"/>
</beans>
e)、在AccountDaoImpl.java的transfer()方法上添加事务注解(定义方法接口)
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public void transfer(String outUser, String inUser, Double money) { // 收款时,收款用户的余额=现有余额+所汇金额
this.jdbcTemplate.update("update account set balance = balance + ? " +
"where username = ?",money, inUser); // 模拟系统运行时的突发性问题
int i = 1/0; // 汇款时,汇款用户的余额=现有余额-所汇金额
this.jdbcTemplate.update("update account set balance = balance-? " +
"where username = ?",money, outUser);
}
f)、运行结果:(异常/by zero报错,说明Spring中的事务管理配置已经生效)
个人总结:
事务处理这方面比较陌生,对某些参数还有些不熟悉,sql很重要!!!其实操作的方式和前面的知识点大同小异。
Java EE学习笔记(五)的更多相关文章
- Java IO学习笔记五:BIO到NIO
作者:Grey 原文地址: Java IO学习笔记五:BIO到NIO 准备环境 准备一个CentOS7的Linux实例: 实例的IP: 192.168.205.138 我们这次实验的目的就是直观感受一 ...
- Java设计模式学习笔记(五) 单例模式
前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 使用单例模式的原因 以Windows任务管理器为例,在Windows系统中,任务管理器是唯 ...
- java基础学习笔记五(抽象类)
java基础学习总结——抽象类 抽象类介绍
- Java基础学习笔记(五) - 常用的API
API介绍 概念:API 即应用编程程序接口.Java API是JDK中提供给我们使用的类说明文档,这些类将底层的代码实现封装.无需关心这些类是如何实现,只需要学习如何使用. 使用:通过API找到需要 ...
- Java基础学习笔记五 Java基础语法之面向对象
面向对象 理解什么是面向过程.面向对象 面向过程与面向对象都是我们编程中,编写程序的一种思维方式.面向过程的程序设计方式,是遇到一件事时,思考“我该怎么做”,然后一步步实现的过程.例如:公司打扫卫生( ...
- Java EE学习笔记(七)
MyBatis的核心配置 1.MyBatis的核心对象 1).SqlSessionFactory是MyBatis框架中十分重要的对象,它是单个数据库映射关系经过编译后的内存镜像,其主要作用是创建Sql ...
- java jvm学习笔记五(实践自己写的类装载器)
欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和 ...
- Java IO学习笔记五
管道流 管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream).管道输入流(PipedInputStream),如果想要进行管道输出,则必须要把输出流连在输入 ...
- Java NIO 学习笔记五 缓冲区补充
1.缓冲区分配 方法 以 ByteBuffer 为例 (1)使用静态方法 ByteBuffer buffer = ByteBuffer.allocate( 500 ); allocate() 方法 ...
随机推荐
- centos 配置
安装 node 源地址: http://my.oschina.net/blogshi/blog/260953 (一) 编译好的文件 简单说就是解压后,在bin文件夹中已经存在node以及npm,如果你 ...
- Opencv— — Circle Filter
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...
- BZOJ2120:数颜色(数状数组套主席树)(带修改的莫对)
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P ...
- Android四种启动模式
四种启动模式 standard(默认) singleTop singleTast singleInstance standard(默认) 系统默认的启动模式. Android是使用返回栈来管理活动的, ...
- kafka数据可靠性深度解读【转】
1 概述 Kakfa起初是由LinkedIn公司开发的一个分布式的消息系统,后成为Apache的一部分,它使用Scala编写,以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分布式处理系统如Cl ...
- py-day17-jquery
jquery实现案例 案例: 1.点赞 <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- 1.17 shell action
一.shell action 1. ##job.properties nameNode=hdfs://hadoop-senior.ibeifeng.com:8020 jobTracker=hadoop ...
- C#项目中一些文件类型说明
designer.cs 是窗体设计器生成的代码文件,作用是对窗体上的控件做初始化工作 (在函数InitializeComponent()中)VS2003以前都把这部分代码放到窗体的cs文件中,由于这 ...
- visualstudio Team Foundation Server 使用教程
一.前沿 Team Foundation Server 是我们开发者使用最多的源代码管理工具.由于自己服务器搭建拉取工作慢的缘故,我使用了微软的 TFS.使用非常方便.快捷.免费.且不公开私有的项目. ...
- Linux locate 文件搜索
在学习 兄弟连 linux教学视频 的时候,我将所学的 linux 命令记录在我的博客中,方便自己查阅. 文件处理命令:locate 基础的命令 命令名称:locate 命令的所在路径:/usr/bi ...