Spring数据库事务管理
程序员文章站
2022-03-30 10:14:16
...
一.简单事务管理
- 用@Transaction 配置事务
配置文件
spring.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:p="http://www.springframework.org/schema/p"
xmlns:stat="http://www.alibaba.com/schema/stat"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.alibaba.com/schema/stat http://www.alibaba.com/schema/stat.xsd">
<context:component-scan base-package="com.qyc.*"></context:component-scan>
<context:property-placeholder location="db.properties"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
</bean>
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis.xml"></property>
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="mapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.qyc.mapper.Mapper"></property>
<property name="sqlSessionFactory" ref="SqlSessionFactory"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 使用@Transaction配置事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qyc.mapper.Mapper">
<select id="selectAllStudents" resultType="com.qyc.pojo.Student">
select * from stu
</select>
<insert id="insertStudent" parameterType="com.qyc.pojo.Student">
insert into stu (name,password)value(#{name},#{password})
</insert>
</mapper>
mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<mappers>
<mapper class="com.qyc.mapper.Mapper"/>
</mappers>
</configuration>
1.1插入单个数据
service.java
package com.qyc.StudentServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.qyc.StudentService.StudentService;
import com.qyc.mapper.Mapper;
import com.qyc.pojo.Student;
@Service
public class StudentServiceImpl implements StudentService{
@Autowired
private Mapper mapper;
@Override
@Transactional(propagation=Propagation.REQUIRES,isolation=Isolation.READ_COMMITTED)
public int insertStudent(Student student) {
int i = mapper.insertStudent(student);
System.out.println("返回值为"+i);
return 1;
}
}
TestDemo.java
package com.qyc.test;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.qyc.StudentService.StudentListService;
import com.qyc.StudentService.StudentService;
import com.qyc.pojo.Student;
public class TestDemo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-basis.xml");
StudentService serviceImpl = (StudentService) applicationContext.getBean("studentServiceImpl");
Student student = new Student("强月城", "123456789");
System.out.println(serviceImlp.insertStudent(student));
}
}
1.2插入多条数据(总结三种类型)实际可以有多种处理方法
- 插入多条数据的方法调用的是插入一条数据的方法
- 注意@Transaction里的参数
- 传播行为
- REQUIRED spring默认传播行为,当方法调用时,如果不存在当前事务,那么创建事务,如果之前方法已经存在事务,则沿用之前的事务
- REQUIRES_NEW 无论是否存在,都会创建新事务
- NESTED 嵌套事务,调用方法如果抛出异常,只回滚自己内部执行的SQL,而不回滚主方法SQL
1.2.1 NO1
- 在插入单个数据方法中,捕获RuntimeException异常
一条
package com.qyc.StudentServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.qyc.StudentService.StudentService;
import com.qyc.mapper.Mapper;
import com.qyc.pojo.Student;
@Service
public class StudentServiceImpl implements StudentService{
@Autowired
private Mapper mapper;
@Override
@Transactional(propagation=Propagation.REQUIRES_NEW,isolation=Isolation.READ_COMMITTED)
public int insertStudent(Student student) {
int i = 0;
// TODO Auto-generated method stub
try {
i = mapper.insertStudent(student);
} catch (Exception e) {
// throw new RuntimeException(e);
// TODO: handle exception
return 0;
}
System.out.println("返回值为"+i);
return 1;
}
}
多条
package com.qyc.StudentServiceImpl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.qyc.StudentService.StudentListService;
import com.qyc.StudentService.StudentService;
import com.qyc.mapper.Mapper;
import com.qyc.pojo.Student;
@Service
public class StudentListServiceImpl implements StudentListService {
private int count = 0;
@Autowired
@Qualifier("studentServiceImpl")
private StudentService studentServiceImpl;
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
public int insertListStudent(List<Student> list) {
// TODO Auto-generated method stub
for (Student student : list) {
count += studentServiceImpl.insertStudent(student);
}
return count;
}
}
TestDemo.java
package com.qyc.test;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.qyc.StudentService.StudentListService;
import com.qyc.StudentService.StudentService;
import com.qyc.pojo.Student;
public class TestDemo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-basis.xml");
StudentListService serviceImlp = (StudentListService) applicationContext.getBean("studentListServiceImpl");
List<Student> list = new ArrayList<Student>();
list.add(new Student("qyc", "qqqyyyc"));
list.add(new Student(null, "123456789"));
list.add(new Student("qcc", "qqqccc"));
System.out.println(serviceImlp.insertListStudent(list));
}
}
1.2.2No2
- 在main方法中设置try catch模块包围调用的方法
- 一条抛异常
- 把一条的@transaction 参数设置为REQUIRES_NEW
1.2.3No3
- 在main方法中设置try catch模块
- 把一条的@transaction 参数设置为REQUIRED
- 一条抛异常
总结:
结构上面源码意义
- requires new 不抛 2条
- requires new 抛 1条
- required 不抛 2条
- required 抛 0条
二.多表操作
2.1俩种情况
2.1.1
- 需要在后面的方法加trycatch语句
- 抛 throw new RuntimeException(e);
package com.qyc.StudentServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import com.qyc.StudentService.StudentService;
import com.qyc.mapper.Mapper;
import com.qyc.pojo.Student;
@Service
public class StudentServiceImpl implements StudentService{
@Autowired
private Mapper mapper;
@Override
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED)
public int insertStudent(Student student) {
int i = 0;
// TODO Auto-generated method stub
try {
i = mapper.insertStudent(student);
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println("返回值为"+i);
return i;
}
}
2.1.2
- throw new RuntimeException(e); 注释掉就可以
- 要在主方法里用try catch包围