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() 方法 ...
随机推荐
- LightOJ1213 Fantasy of a Summation —— 快速幂
题目链接:https://vjudge.net/problem/LightOJ-1213 1213 - Fantasy of a Summation PDF (English) Statisti ...
- runtime之实现对象序列化
/* iOS序列化,将对象转成二进制,保存到本地 */ 定义一个对象,让它实现NSCoding协议,保证对象的编码和解码,person有三个属性 @interface Person : NSObjec ...
- OpenGL之坐标转换(好文-清晰版)
http://blog.csdn.net/zhongjling/article/details/8488844OpenGL之坐标转换(好文-清晰版)
- hadoop集群异常问题总结
1. Could not find or load main class java.library.path=.opt.hadoop.lib 我的环境上是 hadoopopts变量的配置问题,至于为啥 ...
- python多进程执行任务
https://blog.csdn.net/qq_39694935/article/details/84552076 [Python]multiprocessing Pool 进程间通信共享 直接上代 ...
- 「LOJ#10043」「一本通 2.2 例 1」剪花布条 (KMP
题目描述 原题来自:HDU 2087 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? 输入格式 输入数据 ...
- codevs1068乌龟棋
codevs1068乌龟棋 1068 乌龟棋 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamon 题目描述 Descrip ...
- Java应用架构设计模块化模式与OSGI摘录
在Java中,最适合模块化的单元就是Jar文件. 代码层面我们关注的太多了,熟练的开发人员现在很少争论使用模式的好处,也不再识别哪个模式适合当前需要,因为都能够本能地使用各种设计原则和模式,从GoF的 ...
- AndroidStudio设置“自动导入包”
setting –-> Editor –-> General –-> Auto Inport 勾选这两项 单击 Apply –-> ok
- SimpliciTI Sample Applications
Sample Applications 介绍了4个简单的示例应用程序来演示SimpliciTI的各种特性和功能. Simple Peer-To-Peer :two linked End-Devices ...