未添加事务测试
mapper配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//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;
}
@Override
public 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();
}
@Override
public void addUser(Student student) {
StudentDao mapper = sqlSessionTemplate.getMapper(StudentDao.class);
mapper.addUser(student);
}
@Override
public 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” 。