什么是事务?
事务就是一组由于逻辑上紧密关联而合并成的一个整体(工作单元)的多个数据库操作,这些操作要么都执行要么都不执行
事务的四个关键属性(ACID:atomicity、consistency、isolation、durability)?
- 原子性:不可再分,涉及到的多个操作在逻辑上缺一不可(逻辑上是对的)
- 一致性:所有数据都处于满足业务规则的一致性状态(数据是正确的)
- 隔离性:事务往往并发执行因此每个事务都应该与其他事务隔离开来,防止数据损坏
- 持久性:事务执行完成之后对数据的修改永久保存下来,事务对数据的修改应该被写到持久化存储器(硬盘)中;
项目使用事务步骤?
1.xml文件中注解配置事务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.atguigu.book"></context:component-scan>
<context:property-placeholder location="conf/db.properties" />
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务管理器 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 事务管理的是数据库连接池产生的对象(链接对象) -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解驱动 对事务相关的注解进行扫描 解析含义并执行功能-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>
2.@Transaction的属性 作用于Service层
package com.atguigu.book.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.atguigu.book.dao.BookDao;
import com.atguigu.book.exception.MyException;
import com.atguigu.book.service.BookService;
@Service
@Transactional //可以加方法上 也可以加在类上
public class BookServiceImpl implements BookService {
@Autowired
private BookDao dao;
/*
*@Transactional: 对方法中所有操作作为一个事务进行管理
*在方法上只对方法有效果
*在类上对所有的方法都有效果
*
*propagation(传播):A方法和B方法都有事务,当A在调用B时,会将A中的事务传播给B方法,B方法对于事务的处理方式就是事务的传播行为
*@Transactional(propagation=Propagation.REQUIRED) 必须使用调用者的事务
*@Transactional(propagation=Propagation.REQUIRES_NEW) 不使用调用者的事务
*isolation:事务的隔离级别,在并发的情况下,操作数据的一种规定
* 读未提交:脏读、读到一些没有意义的数据1 (针对字段)
* 读已提交:不可重复读2 (针对字段)
* 可重复读:当前正在读的操作不允许其他操作 幻读4(针对行)
* 串行化:单线程 性能低 消耗大8
*
*timeout:在事务强制回滚前最多可以执行(等待)的时间
*
* readOnly:指定当前事务中一系列的操作是否为只读
* 若设置为只读,不管事务中有没有写的操作,MYSQL就会在请求访问数据的时候,不加锁,提高性能
* 但如果有写操作的情况,建议一定不能设置只读所以 readOnly不能乱加
*
* rollbackFor||rollbackClassName||noRollbackFor||noRollbackForClassName
* rollbackFor:因...而回滚 rollbackFor={NullPointerException.class,MyException.class} 表示原因
* norollbackFor:不因...而回滚
* rollbackClassName:异常的权限定性
*
* */
//必须使用调用者的事务
// @Transactional(propagation=Propagation.REQUIRED)
//将调用者的事务挂起 不使用调用者的事务 timeout=3表示3秒内没完成事务的话 将强制回滚
@Transactional(propagation=Propagation.REQUIRES_NEW,timeout=3,rollbackFor={NullPointerException.class,MyException.class})
public void buyBook(String bid, String uid) {
// TODO Auto-generated method stub
/* 测试超时情况
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
Integer price =dao.selectPrice(bid);
dao.updateBalance(uid, price);
dao.updateStock(bid);
}
}
3.事务的传播行为、隔离级别、超时操作、只读、回滚条件
/*
*@Transactional: 对方法中所有操作作为一个事务进行管理
*在方法上只对方法有效果
*在类上对所有的方法都有效果
*
*propagation(传播):A方法和B方法都有事务,当A在调用B时,会将A中的事务传播给B方法,B方法对于事务的处理方式就是事务的传播行为
*@Transactional(propagation=Propagation.REQUIRED) 必须使用调用者的事务
*@Transactional(propagation=Propagation.REQUIRES_NEW) 不使用调用者的事务
*isolation:事务的隔离级别,在并发的情况下,操作数据的一种规定
* 读未提交:脏读、读到一些没有意义的数据1 (针对字段)
* 读已提交:不可重复读2 (针对字段)
* 可重复读:当前正在读的操作不允许其他操作 幻读4(针对行)
* 串行化:单线程 性能低 消耗大8
*
*timeout:在事务强制回滚前最多可以执行(等待)的时间
*
* readOnly:指定当前事务中一系列的操作是否为只读
* 若设置为只读,不管事务中有没有写的操作,MYSQL就会在请求访问数据的时候,不加锁,提高性能
* 但如果有写操作的情况,建议一定不能设置只读所以 readOnly不能乱加
*
* rollbackFor||rollbackClassName||noRollbackFor||noRollbackForClassName
* rollbackFor:因...而回滚 rollbackFor={NullPointerException.class,MyException.class} 表示原因
* norollbackFor:不因...而回滚
* rollbackClassName:异常的权限定性
*
* */
//必须使用调用者的事务
// @Transactional(propagation=Propagation.REQUIRED)
//将调用者的事务挂起 不使用调用者的事务 timeout=3表示3秒内没完成事务的话 将强制回滚
@Transactional(propagation=Propagation.REQUIRES_NEW,timeout=3,rollbackFor={NullPointerException.class,MyException.class})
4.XML方式的事务配置-不用再在方法上使用@Transaction
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.atguigu.book_xml"></context:component-scan>
<context:property-placeholder location="conf/db.properties" />
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务管理器 不管使用注解方式或xml方式配置事务,一定要有dataSourceTransactionManager事务管理器的支持 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 不用注解驱动 <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/> -->
<!-- 配置事务通知 事务管理器相当于一个切面 -->
<tx:advice id="tx" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<!-- 在设置好的切入点表达式下再次进行事务设置 -->
<tx:method name="buyBook" />
<tx:method name="checkOut" />
<!-- 当要管理的方法特别多时 可以用通配符 下面的案例表示以abs开头的方法 -->
<tx:method name="abs*"/>
<!-- 所有的 -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 配置切入点表达式 -->
<aop:config>
<aop:pointcut expression="execution(* com.atguigu.book_xml.service.impl.*.*(..))"
id="pointCut" />
<aop:advisor advice-ref="tx" pointcut-ref="pointCut"/>
</aop:config>
</beans>