本系列笔记均是对b站教程https://www.bilibili.com/video/av47952931 的学习笔记,非本人原创
spring基于xml的声明式事务控制
spring默认使用数据库的隔离级别:
事务的传播行为:
只有查询方法才适用于只读事务
什么是事务的存储点呢?存储点是一个事务内部的提交和回滚的节点:如果当前节点内的操作成功,则提交这一段的操作;如果失败,则回滚到上一节点
<!--spring中基于xml的声明式事务配置步骤-->
<!--1.配置事务管理器-->
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2.配置事务的通知
需要导入事务的约束
此时我们需要导入事务的约束,tx名称空间和约束,同时也需要aop的
使用tx:advice配置事务通知
属性:
id:给事务通知起一个唯一标志
transactionManager:给事务通知提供一个事务管理器引用-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--4.配置事务的属性
isolation:用于指定事务的隔离级别,默认值是DEFAULT,表示使用数据库的默认隔离级别
propagation:用于指定事务的传播行为,默认值是REQUIRED,表示一定会有事务,增删改的选择;查询方法可以选择SUPPORT
read-only:用于指定事务是否只读,只有查询方法才能设置为true,默认是false
rollback-for:用于指定一个异常,当产生该异常时事务回滚;产生其他异常时,事务不回滚,没有默认值,表示任何异常都回滚
no-rollback-for:用于指定一个异常,当产生该异常时事务不回滚;产生其他异常时,事务回滚,没有默认值,表示任何异常都回滚
timeout:用于指定事务的超时时间,默认值是-1,表示永远不超时;如果指定了数值,以秒为单位
-->
<tx:attributes>
<!--为所有的非查询方法配置属性-->
<tx:method name="*" propagation="REQUIRED"read-only="false"/>
<!--为所有的查询方法配置属性(要命名规范)-->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
<!--第二个优先级比第一个高-->
</tx:attributes>
</tx:advice>
<!--3. 配置aop中的通用切入点表达式
-->
<aop:config>
<aop:pointcut id="pt1" expression="execution(* com.jiading.service.impl.*.*(..))"/>
<!--建立切入点表达式和事务通知的对应关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>
注意导包的时候要加上spring-tx:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
spring基于注解的声明式事务控制
先来配置bean.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: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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.jiading"></context:component-scan>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/jd_learning"></property>
<property name="username" value="root"></property>
<property name="password" value="<密码>"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--spring中基于注解的声明式事务配置步骤-->
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2.开启spring对注解事务的支持-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
<!-- 在需要使用事务支持的地方使用@Transactional注解-->
</beans>
可以看到,这里只配置了引入的外部对象,内部的可以由注解完成
可以使用@Transactional注解开启事务支持,这个注解可以加在类上作用于类中所有的方法,也可以加在方法上。如果同时作用,方法上的会覆盖类上的:
package com.jiading.service.impl;
import com.jiading.dao.impl.AccountDaoImpl;
import com.jiading.domain.Account;
import com.jiading.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service("accountService")
//在注解中进行配置
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
public class AccountServiceImpl implements IAccountService {
@Autowired
AccountDaoImpl accountDao;
@Override
public Account findAccountById(Integer accountId) {
Account accountById = accountDao.findAccountById(accountId);
return accountById;
}
@Transactional(propagation = Propagation.SUPPORTS,readOnly = false)
//可以对方法进行单独配置
@Override
public void transfer(String sourceName, String targetName, Float money) {
Account source = accountDao.findAccountByName(sourceName);
Account target = accountDao.findAccountByName(targetName);
source.setMoney(source.getMoney() - money);
target.setMoney(target.getMoney() + money);
accountDao.updateAccount(source);
accountDao.updateAccount(target);
}
}
那么如何改造为纯注解的方式呢?这个前面已经说过了,这里不再示范