文章目录
1、事务操作概念与特性
(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败,那么所有操作都会失败
(2)事务操作的典型场景:银行转账
(3)事务操作四个特性
- 原子性
- 一致性
- 隔离性
- 持久性
2、事务管理操作介绍
- 事务管理操作添加到JavaEE三层结构里面的service层上(业务逻辑层)
- 在Spring中进行事务管理操作,两种方式:编程式事务管理、声明式事务管理,目前的事务操作主要使用声明式事务管理进行实现
- 声明式事务管理操作
- 基于注解方式实现(大多数使用情况)
- 基于xml配置文件方式
- 在Spring中进行声明式事务管理操作,底层使用AOP原理实现
- 在Spring中进行事务管理,这里需要使用到的一个接口:DataSourceTransactionManger,代表事务管理器
3、利用事务操作解决上述银行转账问题(注解方式实现)
- 在Spring配置文件中配置数据库连接池,并配置JdbcTemplate对象
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql:///bank"></property>
<property name="username" value="root"></property>
<property name="password" value="lll159357."></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
<!--JdbcTempla对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
- 在Spring配置文件中配置事务管理器,注入数据源
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<proper name="dataSource" ref="dataSource"></property>
</bean>
- 开启事务注解和组件扫描(1.引入名称空间tx和context;2.开启事务注解和组件扫描)
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--开启组件扫描-->
<context:component-scan base-package="bank_service,bank_dao"></context:component-scan>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
- 创建以下包和类
UserDao:
public interface UserDao {
public void add();
public void reduce();
}
UserDaoImpl:实现UserDao
@Component
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add() {
String sql="update t_user set money=money+? where username=?";
jdbcTemplate.update(sql,100,"mary");
}
@Override
public void reduce() {
String sql="update t_user set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
}
UserService:实现业务操作
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void accountMoney(){
userDao.reduce();
int i = 10/0;
userDao.add();
}
}
- 创建测试类运行测试(没有在业务层添加事务操作)
public class test_bank {
@Test
public void text(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
}
运行前数据库表展示:
报错展示:
运行后数据库表展示:
- 创建测试类运行测试(在业务层添加了事务操作)
(1)@Transactional,这个注解可以添加到类上面,也可以添加到方法上面
(2)如果把这个注解添加到类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务
@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
public void accountMoney(){
userDao.reduce();
int i = 10/0;
userDao.add();
}
}
运行前数据库表展示:
报错展示:
运行后数据库表展示:这段代码前面会执行减少钱的方法,但是因为开启了事务操作,即使中途出现了除零异常,也能够避免出现只减不加的情况出现,因为事务操作会让程序中断之前改变的数据进行回滚复原:
4、注解@Transactional中的相关参数
下面就对以上画红线的六种参数进行介绍
(1)propagation:事务传播行为,通过一个有事务方法调用一个无事务方法,或者反过来
属性值:Propagation.下面表格中的属性值
(2)isolation:事务隔离级别
- 多事务操作之间不会产生影响,不考虑隔离性会产生很多问题
- 有三个读问题:脏读,不可重复读,虚(幻)读
- 脏读:一个未提交事务读取另一个未提交事务的数据
- 不可重复读:一个未提交事务读取到另一提交事务修改数据
- 虚读:一个未提交事务读取到另一提交事务添加数据
- 通过设置事务隔离性,解决读问题
属性值:Isolation.下面表格属性
(3)timeout:超过时间
- 事务需要在一定时间内提交,如果不提交则进行回滚
- 默认值为-1,设置时间以秒为单位进行计算
(4)readOnly:是否只读
- 读:查询操作;写:添加修改删除操作
- readOnly默认值为false,表示可以查询,可以添加修改删除
- 设置readOnly值为true,则只能查询
(5)rollbackFor:回滚
- 设置出现那些异常进行事务的回滚
(6)noRollbackFor:不回滚
- 设置出现那些异常不进行事务的回滚
5、事务操作(XML声明式事务管理)
- 在Spring配置文件中进行相应配置,并且将UserService类中的@Transactional删去
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="bank_service,bank_dao"></context:component-scan>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql:///bank"></property>
<property name="username" value="root"></property>
<property name="password" value="lll159357."></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>
<!--JdbcTempla对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置通知 -->
<tx:advice id="txadvice" >
<!--配置事务参数-->
<tx:attributes>
<tx:method name="accountMoney" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置切入点和切面-->
<aop:config>
<aop:pointcut id="pt" expression="execution(* bank_service.UserService.*(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
</beans>
6、事务操作(完全注解开发实现声明式事务管理)
- 创建配置类,使用配置类替代xml配置文件
@Configuration
@ComponentScan(basePackages = "bank_service")
@ComponentScan(basePackages = "bank_dao")
@EnableTransactionManagement
public class TxConfig {
//创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql:///bank");
druidDataSource.setUsername("root");
druidDataSource.setPassword("lll159357.");
return druidDataSource;
}
//创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//创建事务管理器对象
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
- 数据库操作类和Service类均不变
- 创建测试类
public class test_bank {
@Test
public void text1(){
ApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
}
❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤
若对Spring基础知识感兴趣的可以关注一下博主,我会持续更新Spring基础知识(一边学习一边记录),一起进步,有错误的地方也可以在评论区指出来喔,谢谢大家啦!!!