一:概念
1:编程式事务:由程序员编程事务控制代码
2:声明式事务:
(1):事务控制代码已经由spring写好,程序员只需要声明出哪些方法要进行事务控制,如何事务控制
3:声明式事务针对于业务类(service)的方法
4:事务管理器基于通知(advice)的
二:项目
1:新建包mapper,pojo,service,test
2:新建类
(1)mapper包下
(a):RoleMapper类
package mapper;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import pojo.Role;
public interface RoleMapper {
/**
* 注解可代替mapper.xml配置
* @return
*/
@Select("select * from role")
List<Role> selAll();
}
(2):pojo包下
(a):Role类
package pojo;
public class Role {
private int id;
private String roleName;
private String note;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
@Override
public String toString() {
return "id:"+id+" "+"roleName:"+roleName+" "+"note:"+note;
}
}
(3)service包下
(a):RoleService类
package service;
import java.util.List;
import mapper.RoleMapper;
import pojo.Role;
public class RoleService {
private RoleMapper roleMapper;
public RoleMapper getRoleMapper() {
return roleMapper;
}
public void setRoleMapper(RoleMapper roleMapper) {
this.roleMapper = roleMapper;
}
public List<Role> show(){
return roleMapper.selAll();
}
}
(4):test包下
(a):MainTest类
package test;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Role;
import service.RoleService;
public class MainTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
String[] names=ac.getBeanDefinitionNames();
for(String name:names) {
System.out.println(name);
}
RoleService rs=ac.getBean("roleService",RoleService.class);
List<Role> list=rs.show();
for(Role l:list) {
System.out.println(l);
}
}
}
3:src目录下配置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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
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" default-autowire="byName">
<!-- 数据源封装类。数据源:获取数据库连接 ,spring-jdbc.jar中-->
<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/ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 创建SqlSessionFactory对象 -->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接来源于dataSource -->
<property name="dataSource" ref="dataSource"></property>
<!-- 给包下的类起别名,别名为类名 -->
<property name="typeAliasesPackage" value="pojo"></property>
<!-- 整合mybatis的配置文件 -->
<!--<property name="configLocation" value="mybatis-config.xml"/>-->
</bean>
<!-- 扫描器相当于mybatis.xml中的mappers下的package标签,
扫描mapper包后会给对应接口创建对象,并生成id为小驼峰类名的bean-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 要扫描哪个包 -->
<property name="basePackage" value="mapper"></property>
<!-- 和factory产生关系 -->
<!-- 当加载属性文件时,下面这个配置异常,应使用sqlSessionFactoryBeanName -->
<!-- <property name="sqlSessionFactory" ref="factory"></property> -->
<property name="sqlSessionFactoryBeanName" value="factory"></property>
</bean>
<!-- 由spring管理service类 -->
<bean id="roleService" class="service.RoleService">
<property name="roleMapper" ref="roleMapper"></property>
</bean>
<!-- spring-jdbc.jar中 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置声明式事务 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 哪些方法需要有事务控制 -->
<!-- 方法以sel开头事务管理 -->
<tx:method name="sel*"/>
<!-- 所有方法事务管理 -->
<tx:method name="*"/>
<!-- selAll方法事务管理 -->
<tx:method name="selAll"/>
</tx:attributes>
</tx:advice>
<!-- 配置通知 -->
<aop:config>
<!-- 切点的配置范围较大 -->
<aop:pointcut expression="execution(* service.*.*(..))" id="mypoint"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
</aop:config>
</beans>
4:运行MainTest类,结果如下
三:声明式事务中的属性解释(<tx:method />标签)
1:name="" 哪些方法需要有事务控制
(1):支持*通配符
2:readonly="boolean" 是否是只读事务
(1):true:告诉数据库此事务是只读事务
(2):false(默认)可读可写事务
3:propagation 控制事务传播行为
(1):当一个具有事务控制的方法被另一个具有事务控制方法调用时,需要如何管理事务
(2):REQUIRED(默认值):如果当前有事务就在事务中执行。如果当前没有事务,就新建一个事务
(3):SUPPORTS:如果当前有事务就在事务中执行,如果没有事务,就在非事务下执行
(4):MANDATORY:必须在事务内部执行,如果当前有事务,就在事务中执行,没有事务就报错
(5):REUQIRES_NEW:必须在事务中执行。如果当前没有事务,新建事务。如果当前有事务,将当前事务挂起
(6):NOT_SUPPORTED:必须在非事务下执行。如果当前没有事务,正常执行,如果当前有事务,将当前事务挂起
(7):NEVER:必须在非事务下执行。如果当前没有事务正常执行,如果当前有事务,报错
(8):NESTED:必须在事务状态下执行。如果没有事务,新建事务。如果当前有事务,创建一个嵌套事务
4:isolation="" 事务隔离级别
(1):DEFAULT:默认值,由底层数据库自动判断应该使用怎样的事务隔离级别
(2):READ_UNCOMMITTED:可以读取未提交的数据,可能出现幻读,不可重复读,脏读。效率最高
(3):READ_COMMITTED:只能读取其他事务已提交的数据,可以防止脏读,可能出现不可重复读和幻读
(4):REPEATABLE_READ:读取的数据被添加锁,防止其他事务修改数据,可以防止不可重复读,脏读,可能出现幻读
(5):REPEATABLE:排队操作,对整个表添加锁。一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表(最安全的,也是效率最低的)
5:rollback-for="异常类型全限定路径"
(1):当什么异常时需要进行回滚
(2):建议给定该属性值,当手动抛出异常一定要给出该属性值
6:no-rollback-for=""
(1):当出现什么异常时不回滚事务