mybatis使用、事务

maven依赖

<!-- mybatis -->
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.4.6</version>
</dependency>

<!-- mysql连接驱动 -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>6.0.6</version>
</dependency>

mybatis核心组件:

SqlSessionFactoryBuilder(构造器):它会根据配置或者代码来生成SqlSessionFactory,采用的是分步构建的Builder模式。

SqlSessionFactory(工厂接口):依靠它来生成SqlSession。使用的是工厂模式。

SqlSession(会话):一个既可以发送sql执行返回结果,也可以获取Mapper的接口。

Sql Mapper(映射器):由JAVA接口和XML(或注解)构成,需要给出对应的sql和映射规则,它负责发送sql去执行并返回结果。

一、使用xml配置文件构建SqlSessionFactory

配置文件内容:mybatis配置文件详解 http://www.mybatis.org/mybatis-3/zh/configuration.html

<?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>
   <!--<properties>
      <property name="password" value="root"/>
   </properties>-->

   <settings>
      <!--自动映射-->
      <setting name="autoMappingBehavior" value="PARTIAL"/>
      <!--开启自动驼峰命名映射-->
      <!--<setting name="mapUnderscoreToCamelCase" value="true"/>-->
   </settings>

   <!-- 别名 -->
   <typeAliases>
      <!--通过扫包-->
      <package name="com.mybatis"/>
      <!--<typeAlias alias="user" type="com.mybatis.core.User"/>-->
   </typeAliases>

   <!--数据库配置-->
   <environments default="development">
      <environment id="development">
         <transactionManager type="JDBC"/>
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
         </dataSource>
      </environment>
   </environments>

   <!--映射器-->
   <mappers>
      <!--使用注解实现映射器-->
      <!--<mapper class="com.mybatis.dao.UserAnnotationMapper"/>
      <package name="com.mybatis.dao"/>-->
      <!--使用xml实现映射器(优先,同时定义会覆盖注解方式)-->
      <mapper resource="mapper/UserMapper.xml"/>
   </mappers>
</configuration>

Mybatis映射器:

<?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.mybatis.dao.UserMapper">

   <resultMap type="user" id="ResultMap">
      <result property="id" column="id" jdbcType="VARCHAR"/>
      <result property="userName" column="user_name" jdbcType="VARCHAR"/>
      <result property="password" column="user_password" jdbcType="VARCHAR"/>
   </resultMap>

   <sql id="Base_Column">
      id,user_name,user_password
   </sql>

   <sql id="UserCondition">
      <where>
         1= 1
         <if test="userName != null and userName != ''">
            AND user_name = #{userName}
         </if>
      </where>
   </sql>

   <select id="findUserByName" parameterType="java.lang.String" resultMap="ResultMap">
      select
      <include refid="Base_Column"/>
      from p_user where user_name = #{userName}
   </select>

   <select id="findUserList" resultMap="ResultMap" parameterType="user">
      SELECT
      <include refid="Base_Column"/>
      FROM p_user
      <include refid="UserCondition"/>
   </select>

   <!--自动映射,无需resultMap跟对象映射-->
   <select id="findUserById" parameterType="java.lang.String" resultType="user">
      select
      id as id,
      user_name as userName,
      user_password as password
      from p_user where id = #{id}
   </select>

   <select id="findUserByIdCp" resultType="user">
      select
      id as id,
      user_name as userName,
      user_password as password
      from p_user where id = #{userId}
   </select>

   <update id="updateUser" parameterType="user">
      update p_user set user_name = #{userName},user_password = #{password} WHERE id = #{id}
   </update>

   <insert id="saveUser" parameterType="user">
      insert into p_user
      <trim prefix="(" suffix=")" suffixOverrides=",">
         <if test="id != null and id != ''">
            id,
         </if>
         <if test="userName != null and userName != ''">
            user_name,
         </if>
         <if test="password != null and password != ''">
            user_password,
         </if>
      </trim>
      <trim prefix="values (" suffix=")" suffixOverrides=",">
         <if test="id != null and id != ''">
            #{id},
         </if>
         <if test="userName != null and userName != ''">
            #{userName},
         </if>
         <if test="password != null and password != ''">
            #{password},
         </if>
      </trim>
   </insert>

   <select id="updateTest" parameterType="user">
      insert into p_user
      <trim prefix="(" suffix=")" suffixOverrides=",">
         <if test="id != null and id != ''">
            id,
         </if>
         <if test="userName != null and userName != ''">
            user_name,
         </if>
         <if test="password != null and password != ''">
            user_password,
         </if>
      </trim>
      <trim prefix="values (" suffix=")" suffixOverrides=",">
         <if test="id != null and id != ''">
            #{id},
         </if>
         <if test="userName != null and userName != ''">
            #{userName},
         </if>
         <if test="password != null and password != ''">
            #{password},
         </if>
      </trim>
   </select>

   <select id="findByRowBounds" resultType="user">
      select
      id as id,
      user_name as userName,
      user_password as password
      from p_user
   </select>
</mapper>
package com.mybatis.dao;

import com.mybatis.core.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.RowBounds;

import java.util.List;

/**
 * @author zqq
 */
public interface UserMapper {
    
    

    User findUserByName(String userName);

    List<User> findUserList(User user);

    void updateUser(User user);

    void saveUser(User user);

    void updateTest(User user);

    User findUserById(String id);

    User findUserByIdCp(@Param("userId") String id);

    /**
     * 分页查询
     * @param user user参数
     * @param rowBounds 分页参数,只需要加在接口上mybatis自动识别
     * @return
     */
    List<User> findByRowBounds(@Param("params") User user, RowBounds rowBounds);

}

构建SqlSession发送sql:

@Test
public void demo1(){
    
    
    //配置文件位置
    String resource = "conf/mybatis-config.xml";
    try {
    
    
        //读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //通过SqlSessionFactoryBuilder的build方法构建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //打开会话SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //获取mapper映射器执行sql
        List<User> list = userMapper.findUserList(new User());
        list.forEach(u -> {
    
    
            //输出查询出的信息
            System.out.println(u.toString());
        });
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

事务管理器TransactionManager

TransactionManager提供了两个实现类,需要实现Transaction接口org.apache.ibatis.transaction.Transaction

public interface Transaction {
    
    
    Connection getConnection() throws SQLException;
	
    //提交事务
    void commit() throws SQLException;

    //回滚
    void rollback() throws SQLException;
	
    //关闭
    void close() throws SQLException;

    Integer getTimeout() throws SQLException;
}

TransactionManager提供了两个实现类:JdbcTransaction和ManagedTransaction。都继承了Transaction接口

配置开启事务:

<!--数据库配置-->
<environments default="development">
   <environment id="development">
      <!--jdbc方式-->
      <transactionManager type="JDBC"/>
      <!--<transactionManager type="MANAGED"/>-->
      <dataSource type="POOLED">
         <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
         <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>
         <property name="username" value="root"/>
         <property name="password" value="root"/>
      </dataSource>
   </environment>
</environments>

JDBC使用JdbcTransactionFactory生成的JdbcTransaction对象实现。它是以JDBC方式对数据库的提交和回滚进行操作。

MANAGED使用ManagedTransactionFactory生成的ManagedTransaction对象实现。它的提交和回滚不用任何操作,而是把事务交给容器处理。

 /**
  * 事务
  */
@Test
public void test(){
    
    
    SqlSessionFactory sqlSessionFactory = null;
    String resource = "conf/mybatis-config.xml";
    SqlSession sqlSession = null;
    try {
    
    
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        sqlSession = sqlSessionFactory.openSession();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    try {
    
    
        User user = new User();
        user.setId(UUID.randomUUID().toString().replaceAll("-",""));
        user.setUserName("testName");
        user.setPassword("123456");
        userMapper.saveUser(user);
        //报错回滚事务
        //System.out.println(1/0);
        sqlSession.commit();
        //提交事务
    }catch (Exception e){
    
    
        e.printStackTrace();
        //事物回滚
        sqlSession.rollback();
    }finally {
    
    
        //关闭会话
        sqlSession.close();
    }
}

自定义事务:

定义事务类,继承JdbcTransaction类,实现Transaction接口(不实现也可以,父类JdbcTransaction已经实现),重写方法。

/**
 * 自定义事务类
 */
public class MyTransaction extends JdbcTransaction {
    
    

    public MyTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
    
    
        super(ds, desiredLevel, desiredAutoCommit);
    }

    @Override
    public Connection getConnection() throws SQLException {
    
    
        return super.getConnection();
    }

    @Override
    public void commit() throws SQLException {
    
    
        System.out.println("自定义事务commit");
        super.commit();
    }

    @Override
    public void rollback() throws SQLException {
    
    
        System.out.println("自定义事务rollback");
        super.rollback();
    }

    @Override
    public void close() throws SQLException {
    
    
        System.out.println("自定义事务close");
        super.close();
    }

    @Override
    protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
    
    
        super.setDesiredAutoCommit(desiredAutoCommit);
    }

    @Override
    protected void resetAutoCommit() {
    
    
        super.resetAutoCommit();
    }

    @Override
    protected void openConnection() throws SQLException {
    
    
        super.openConnection();
    }

    @Override
    public Integer getTimeout() throws SQLException {
    
    
        return super.getTimeout();
    }

    public MyTransaction(Connection connection) {
    
    
        super(connection);
    }
}

定义事务工厂,实现TransactionFactory事务工厂接口,将返回的事务类改成自定义的事务类。

/**
 * 自定义事务工厂
 */
public class MyTransactionFactory implements TransactionFactory {
    
    
    @Override
    public void setProperties(Properties properties) {
    
    

    }

    @Override
    public Transaction newTransaction(Connection connection) {
    
    
        return new MyTransaction(connection);
    }

    @Override
    public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel transactionIsolationLevel, boolean b) {
    
    
        return new MyTransaction(dataSource,transactionIsolationLevel,b);
    }
}

修改配置文件,配上自定义的事务工厂:

<!--数据库配置-->
<environments default="development">
   <environment id="development">
      <!--<transactionManager type="JDBC"/>-->
      <!--自定义事务配置-->
      <transactionManager type="com.mybatis.transaction.MyTransactionFactory"/>
      <dataSource type="POOLED">
         <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
         <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>
         <property name="username" value="root"/>
         <property name="password" value="root"/>
      </dataSource>
   </environment>
</environments>

测试回滚成功:

@Test
public void test(){
    
    
    SqlSessionFactory sqlSessionFactory = null;
    String resource = "conf/mybatis-config.xml";
    SqlSession sqlSession = null;
    try {
    
    
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        sqlSession = sqlSessionFactory.openSession();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    try {
    
    
        User user = new User();
        user.setId(UUID.randomUUID().toString().replaceAll("-",""));
        user.setUserName("name");
        user.setPassword("pwd");
        userMapper.saveUser(user);
        //报错回滚事务
        System.out.println(1/0);
        sqlSession.commit();
        //提交事务
    }catch (Exception e){
    
    
        e.printStackTrace();
        //事物回滚
        sqlSession.rollback();
    }finally {
    
    
        //关闭会话
        sqlSession.close();
    }
}

猜你喜欢

转载自blog.csdn.net/zhaoqingquanajax/article/details/113958262