一、MyBatis事务管理
SqlSession对象
- getMapper(DAO.class):获取Mapper(DAO接口的实体类)
- 事务管理
1.1 手动提交事务
手动事务管理
当我们获取sqlSession对象时,就默认开启了事务;
当一系列业务操作完成之后,我们需要手动提交事务 :sqlSession.commit()
当操作出现异常,调用事务回滚方法:sqlSession.rollback()
@Test
public void deleteStudent() {
SqlSession sqlSession = null;
try{
//1.当我们获取sqlSession对象时,就默认开启了事务
sqlSession = MyBatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
int i = studentDao.deleteStudent(9);
//2.当一系列业务操作完成之后,我们需要手动提交事务
sqlSession.commit();
}catch (Exception e){
//3.当操作出现异常,调用事务回滚方法
sqlSession.rollback();
}finally {
sqlSession.close();
}
}
1.2 自动提交事务
通过SqlSessionFactory调用openSession方法获取sqlSession对象时,可以通过参数设置事务是否自动提交
如果参数设置为true,表示自动提交事务:sqlSessionFactory.openSession(true);
如果参数为空,则默认是fales,表示手动提交:sqlSessionFactory.openSession(true);
1.3 案例
数据准备
CREATE TABLE `students` (
`stu_num` char(8) NOT NULL,
`stu_name` varchar(20) NOT NULL,
`stu_denger` char(2) NOT NULL,
`stu_age` int NOT NULL,
`stu_tel` char(11) NOT NULL,
`stu_qq` varchar(11) DEFAULT NULL,
`cid` int DEFAULT NULL,
PRIMARY KEY (`stu_num`),
KEY `FK_STUDENT_CLASS` (`cid`),
CONSTRAINT `FK_STUDENT_CLASS` FOREIGN KEY (`cid`) REFERENCES `class` (`class_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('1', '蔡文姬', '女', '18', '123312312', '877877', '2');
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('2', '刘禅', '男', '26', '15688887878', '332212', '1');
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('3', '大乔', '女', '19', '13232322232', '4443322', '1');
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('4', '小明', '男', '30', '13567899876', '8879778', '2');
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('5', '鲁班大师', '男', '58', '13566656556', '9999899', '2');
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('6', '墨子', '男', '38', '13788787878', '878888', NULL);
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('7', '瑶', '女', '17', '136667673', '111221', NULL);
INSERT INTO `db_test`.`students` (`stu_num`, `stu_name`, `stu_denger`, `stu_age`, `stu_tel`, `stu_qq`, `cid`) VALUES ('8', '张飞', '男', '88', '13667565656', NULL, '2');
MyBatisUtil工具类
package com.feng.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @program: mybatis_project
* @description: MyBatis工具类,提供getSqlSession和getMapper方法
* @author: FF
* @create: 2024-11-27 20:08
**/
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory;
//为SqlSession加锁
private static final ThreadLocal<SqlSession> sqlSessionlock = new ThreadLocal<>();
static {
InputStream inputStream = null;
try {
//构建sqlSession工厂
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
sqlSessionFactory = builder.build(inputStream);
inputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 通过sqlSessionFactory,获取sqlSession对象(private不对外)
* @Param: [isAutoCommit]
* @return: org.apache.ibatis.session.SqlSession
* @Author: FF
* @Date: 2024/11/27
*/
private static SqlSession getSqlSession(boolean isAutoCommit){
SqlSession sqlSession = sqlSessionlock.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession(isAutoCommit);
sqlSessionlock.set(sqlSession);
}
return sqlSession;
}
/**
* @Description: 获取sqlSession对象,默认手动提交事务(public对外)
* @Param: []
* @return: org.apache.ibatis.session.SqlSession
* @Author: FF
* @Date: 2024/11/27
*/
public static SqlSession getSqlSession(){
return getSqlSession(false);
}
/**
* @Description: 提供getMapper方法,获取mapper代理对象,默认自动提交事务
* @Param: [c]
* @return: T
* @Author: FF
* @Date: 2024/11/27
*/
public static <T extends Object> T getMapper(Class<T> c){
return getSqlSession(true).getMapper(c);
}
}
Student.java
package com.feng.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Student {
private String stu_num;
private String stu_name;
private int stu_age;
private String stu_denger;
private String stu_tel;
private String stu_qq;
private int cid;
}
StudentDao.java
package com.feng.dao;
import com.feng.pojo.Student;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface StudentDao {
public int addStudent(Student student);
public int deleteStudent(int id);
public int updateStudent(Student student);
public List<Student> selectAllStudent();
public Student selectStudentById(String id);
public int countStudent();
public List<Student> selectStudentByPage(@Param("start") int start, @Param("pageSize") int pageSize);
}
StudentMapper.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相当与DAO接口的实现类,namespace属性要指定实现DAO接口的全限定名-->
<mapper namespace="com.feng.dao.StudentDao">
<resultMap id="studentMap" type="com.feng.pojo.Student">
<id column="stu_num" property="stu_num"></id>
<result column="stu_name" property="stu_name"></result>
<result column="stu_age" property="stu_age"></result>
<result column="stu_denger" property="stu_denger"></result>
<result column="stu_tel" property="stu_tel"></result>
<result column="stu_qq" property="stu_qq"></result>
<result column="cid" property="cid"></result>
</resultMap>
<insert id="addStudent" parameterType="com.feng.pojo.Student" useGeneratedKeys="true" keyProperty="stu_num">
insert into students(stu_num,stu_name,stu_age,stu_denger,stu_tel,stu_qq,cid)
values (#{stu_num},#{stu_name},#{stu_age},#{stu_denger},#{stu_tel},#{stu_qq},#{cid})
</insert>
<delete id="deleteStudent">
delete from students where stu_num = #{stu_num}
</delete>
<update id="updateStudent">
update students set
stu_num = #{stu_num},stu_name=#{stu_name},stu_age=#{stu_age},stu_denger=#{stu_denger},
stu_tel=#{stu_tel},stu_qq=#{stu_qq},cid=#{cid}
where
stu_num = #{stu_num}
</update>
<select id="selectAllStudent" resultType="com.feng.pojo.Student" resultMap="studentMap">
select * from students
</select>
<select id="selectStudentById" resultMap="studentMap">
select * from students where stu_num = #{stu_num}
</select>
<select id="countStudent" resultType="int">
select count(1) from students;
</select>
<select id="selectStudentByPage" resultMap="studentMap">
select * from students limit #{start},#{pageSize}
</select>
</mapper>
mybatis-config.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>
<!--配置数据库连接信息-->
<environments default="mysql">
<environment id="mysql">
<!--用于配置数据库管理方式-->
<transactionManager type="JDBC">
</transactionManager>
<!--配置数据库连接方式-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db_test?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--需要将映射文件添加到主文件中-->
<mappers>
<mapper resource="mappers/StudentMapper.xml"></mapper>
</mappers>
</configuration>
测试类
package com.feng.dao;
import com.feng.pojo.Student;
import com.feng.utils.MyBatisUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import static org.junit.Assert.*;
public class StudentDaoTest {
/**
* @Description: 添加方法测试,未使用MyBatisUtils工具类,全部手写
* @Param: []
* @return: void
* @Author: FF
* @Date: 2024/11/27
*/
@org.junit.Test
public void addStudent() throws IOException {
//加载mybatis配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//构建session工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//会话工厂
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(inputStream);
//会话(连接)
SqlSession sqlSession = factory.openSession();
//通过会话,获取dao对象
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
//测试dao方法
Student student = new Student();
student.setStu_num("9");
student.setStu_name("太乙真人");
student.setStu_age(88);
student.setStu_denger("男");
student.setStu_tel("123312312");
student.setStu_qq("877877");
student.setCid(2);
int i = studentDao.addStudent(student);
//手动提交事务
sqlSession.commit();
//关闭会话
sqlSession.close();
//关闭流
inputStream.close();
System.out.println(i);
}
/**
* @Description: 删除方法测试,调用MyBatisUtil.getSqlSession()方法,默认手动提交事务
* @Param: []
* @return: void
* @Author: FF
* @Date: 2024/11/27
*/
@Test
public void deleteStudent() {
SqlSession sqlSession = null;
try{
//1.当我们获取sqlSession对象时,就默认开启了事务(getSqlSession()方法,默认的事务提交方式是手动提交)
sqlSession = MyBatisUtil.getSqlSession();
StudentDao studentDao = MyBatisUtil.getMapper(StudentDao.class);
int i = studentDao.deleteStudent(9);
//2.当一系列业务操作完成之后,我们需要手动提交事务
sqlSession.commit();
System.out.println(i);
}catch (Exception e){
//3.当操作出现异常,调用事务回滚方法
sqlSession.rollback();
}
}
/**
* @Description: 修改方法测试,调用MyBatisUtil.getMapper()方法,默认自动提交事务
* @Param: []
* @return: void
* @Author: FF
* @Date: 2024/11/27
*/
@Test
public void updateStudent() throws IOException {
//MyBatisUtil.getMapper(StudentDao.class)方法默认的是自动提交事务
StudentDao studentDao = MyBatisUtil.getMapper(StudentDao.class);
Student student = new Student();
student.setStu_num("1");
student.setStu_name("蔡文姬");
student.setStu_age(18);
student.setStu_denger("女");
student.setStu_tel("123312312");
student.setStu_qq("877877");
student.setCid(2);
int i = studentDao.updateStudent(student);
assertEquals(1, 1);
}
@Test
public void selectAllStudent() {
StudentDao studentDao = MyBatisUtil.getMapper(StudentDao.class);
List<Student> students = studentDao.selectAllStudent();
assertNotNull(students);
System.out.println(students.size());
for (Student student : students) {
System.out.println(student);
}
}
@Test
public void selectStudentById() throws IOException {
StudentDao studentDao = MyBatisUtil.getMapper(StudentDao.class);
Student student = studentDao.selectStudentById("3");
System.out.println(student);
}
@Test
public void countStudent() throws IOException {
StudentDao studentDao = MyBatisUtil.getMapper(StudentDao.class);
int count = studentDao.countStudent();
System.out.println(count);
}
@Test
public void selectStudentByPage() {
StudentDao mapperer = MyBatisUtil.getMapper(StudentDao.class);
List<Student> students = mapperer.selectStudentByPage(0,5);
assertNotNull(students);
System.out.println(students.size());
for (Student student : students) {
System.out.println(student);
}
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.feng</groupId>
<artifactId>mybatis_project</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>mybatis_project Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.2.0</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>mybatis_project</finalName>
</build>
</project>
工程目录结构 |
---|