spring 声明式事务
未添加事务测试
mapper配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.cht.dao.StudentDao"><resultMap id="StudentMap" type="com.cht.model.Student"><id property="studentId" column="s_id"/><result property="studentNm" column="s_nm"/><result property="age" column="s_age"/><result property="score" column="s_score"/></resultMap><select id="queryStudentList" resultMap="StudentMap">select s_id,s_nm,s_age,s_score from student</select><insert id="addUser" parameterType="com.cht.model.Student" useGeneratedKeys="true" keyProperty="studentId">insert into student (s_nm,s_age,s_score) values (#{studentNm},#{age},#{score})</insert><delete id="deletUser" parameterType="int">delete from student where s_id = #{studeId}</delete></mapper>
接口:
public interface StudentDao {List<Student> queryStudentList();void addUser(Student student);void deletUser(@Param("studentId") int studentId);
}
实现类:
public class StudentDaoImpl implements StudentDao {private static final Logger logger = LoggerFactory.getLogger(StudentDaoImpl.class);/*** spring容器引用对象注入*/private SqlSessionTemplate sqlSessionTemplate;public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {this.sqlSessionTemplate = sqlSessionTemplate;}@Overridepublic List<Student> queryStudentList() {StudentDao mapper = sqlSessionTemplate.getMapper(StudentDao.class);Student student = new Student("小强123", 19, 88);addUser(student);logger.info("插入成功:{}", student);deletUser(student.getStudentId());return mapper.queryStudentList();}@Overridepublic void addUser(Student student) {StudentDao mapper = sqlSessionTemplate.getMapper(StudentDao.class);mapper.addUser(student);}@Overridepublic void deletUser(int studentId) {StudentDao mapper = sqlSessionTemplate.getMapper(StudentDao.class);mapper.deletUser(studentId);}}
测试类:
public class Test {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");// 动态代理获取接口的代理类StudentDao studentDao = applicationContext.getBean("studentDaoImpl", StudentDao.class);List<Student> students = studentDao.queryStudentList();for (Student student : students) {System.out.println(student);}}
}
测试验证:
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@319bc845] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1bdf8190] will not be managed by Spring
==> Preparing: insert into student (s_nm,s_age,s_score) values (?,?,?)
==> Parameters: 小强123(String), 19(Integer), 88(Integer)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@319bc845]
2025-09-13 17:56:01 [main] INFO com.cht.Impl.StudentDaoImpl - 插入成功:Student(studentId=10045, studentNm=小强123, age=19, score=88)
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@560513ce] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@37fbe4a8] will not be managed by Spring
==> Preparing: delete from student where s_id = ?
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@560513ce]
Exception in thread "main" org.mybatis.spring.MyBatisSystemException:
### Error updating database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'studeId' not found. Available parameters are [studentId, param1]
未配置事务时,执行查询方法中当删除报错时,新增还是会执行成功。我们期望的是如果删除失败则新增失败,要保证数据的原子性
spring声明式事务
基于aop实现,切记导入aop织入依赖
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.22.1</version><scope>runtime</scope> </dependency> <!-- AspectJ运行时核心库 --> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.22.1</version> </dependency>
在spring容器中配置事务
<!-- 注入事务管理 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="driverManagerDataSource"/></bean><!-- 事务通知 --><tx:advice id="transactionAdvice"><tx:attributes><!-- * 所有方法 ;propagation 传播行为一般都是用REQUIRED --><tx:method name="*"/></tx:attributes></tx:advice><!-- 事务生效的切入点 --><aop:config><aop:pointcut id="cut" expression="execution(* com.cht.Impl.StudentDaoImpl.*(..))"/><aop:advisor advice-ref="transactionAdvice" pointcut-ref="cut"/></aop:config>
再次测试验证:
从数据库查询,并未查询到插入的这条记录,事务生效。
当开启事务时,创建sqlSession时,会先注册一个事务,开启事务后续的释放事务,以及如何实现回滚的后续再补充吧。
开启事务和未开启事务 最突出的不同点:
开启事务后,日志里会有“Registering transaction synchronization for SqlSession” 。