Mga butangMyBatis nga artikulo

MyBatis

  1. MyBatis 开发步骤:

    • 添加 MyBatis 的坐标

      <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.9</version>
      </dependency>
    • 创建 user 数据表
    • 创建 User 实体类
    • 编写映射文件 UserMapper.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="userMapper">
      
          <select id="findAll" resultType="com.domain.User">
              select * from user
          </select>
      
      </mapper>
    • 编写核心文件 SqlMapConfig.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="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/test"/>
                      <property name="username" value="root"/>
                      <property name="password" value="jie13727507037"/>
                  </dataSource>
              </environment>
          </environments>
      
          <!-- 加载映射文件 -->
          <mappers>
              <mapper resource="com.mapper\UserMapper.xml"/>
          </mappers>
      
      </configuration>
    • 编写测试类

      public void test1() throws IOException {
          // 加载核心配置文件
          InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
          // 获得 SQLSession 工厂对象
          SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
          // 获得 session 会话对象
          SqlSession sqlSession = sqlSessionFactory.openSession();
          // 执行操作     参数:namespace+语句id
          List<User> userList = sqlSession.selectList("userMapper.findAll");
          // 打印数据
          System.out.println(userList);
          // 释放资源
          sqlSession.close();
      }
  2. 映射文件概述

    image-20220630141304364

  3. MyBatis 的插入操作注意问题

    • 插入语句使用 insert 标签
    • 在映射文件中使用 parameterType 属性指定要插入的数据类型
    • Sql 语句中使用 #{实例属性名} 的方式引用实体中的属性值
    • 插入操作使用的 API 是 sqlSession.insert("namespace.id", 实体对象);
    • 插入操作涉及数据库数据变化,所以要使用 sqlSession对象显示的提交事务,即 sqlSession.commit()
    <?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="userMapper">
    
        <!-- 查询操作 -->
        <select id="findAll" resultType="com.domain.User">
            select * from user
        </select>
    
        <!-- 插入操作 -->
        <insert id="save" parameterType="com.domain.User">
            insert into user values(#{id}, #{username}, #{password})
        </insert>
    
    </mapper>
    public void test2() throws IOException {
    
        // 模拟 user 对象
        User user = new User();
        user.setUsername("tom");
        user.setPassword("abc");
    
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 获得 SQLSession 工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        // 获得 session 会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 执行操作     参数:namespace+语句id
        sqlSession.insert("userMapper.save", user);
    
        // mybatis 执行更新操作  需要提交事务
        sqlSession.commit();
    
        // 释放资源
        sqlSession.close();
    }
  4. MyBatis 修改操作注意问题

    • 修改语句使用 update 标签
    • 修改操作使用的 API 是 sqlSession.update("namespace.id", 实体对象);
    <!-- 修改操作 -->
    <update id="update" parameterType="com.domain.User">
        update user set username=#{username}, password=#{password} where id=#{id}
    </update>
    public void test3() throws IOException {
    
        // 模拟 user 对象
        User user = new User();
        user.setId(7);
        user.setUsername("lucy");
        user.setPassword("123");
    
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 获得 SQLSession 工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        // 获得 session 会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 执行操作     参数:namespace+语句id
        sqlSession.update("userMapper.update", user);
    
        // mybatis 执行更新操作  需要提交事务
        sqlSession.commit();
    
        // 释放资源
        sqlSession.close();
    }
  5. MyBatis 删除操作注意问题

    • 删除语句使用 delete 标签
    • Sql 语句中使用 #{任意字符串} 方式引用传递的单个参数
    • 删除操作使用的 API 是 sqlSession.delete("namespace.id", Object);
    <!-- 删除操作 -->
    <delete id="delete" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>
    public void test4() throws IOException {
    
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 获得 SQLSession 工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        // 获得 session 会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 执行操作     参数:namespace+语句id
        sqlSession.delete("userMapper.delete", 7);
    
        // mybatis 执行更新操作  需要提交事务
        sqlSession.commit();
    
        // 释放资源
        sqlSession.close();
    }
  6. MyBatis 核心配置文件常用配置

    • properties 标签:改标签可以加载外部的 properties 文件

      <!-- 加载外部 properties 文件 -->
      <properties resource="jdbc.properties"/>
    • typeAliases 标签:设置类型别名

      <!-- 定义别名 -->
      <typeAliases>
          <typeAlias type="com.domain.User" alias="user"/>
      </typeAliases>
    • mappers 标签:加载映射配置

      <!-- 加载映射文件 -->
      <mappers>
          <mapper resource="com.mapper/UserMapper.xml"/>
      </mappers>
    • environments 标签:数据源环境配置标签

      <!-- 配置数据源环境 -->
      <environments default="development">
          <environment id="development">
              <transactionManager type="JDBC"/>
              <dataSource type="POOLED">
                  <property name="driver" value="${jdbc.driver}"/>
                  <property name="url" value="${jdbc.url}"/>
                  <property name="username" value="${jdbc.username}"/>
                  <property name="password" value="${jdbc.password}"/>
              </dataSource>
          </environment>
      </environments>
  7. MyBatis 相应 API

    • SqlSession 工厂构造器 SqlSessionFactory build(InputStream inputstream)

      // 加载核心配置文件
      InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
      // 获得 SQLSession 工厂对象
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    • SqlSession 工厂对象 SqlSessionFactory

      • openSession():会默认开启一个事务,但事务不会自动提交,也就是一位置需要手动提交该事务,更新操作数据才会持久化到数据库中
      • openSession(boolean autoCommit):参数为是否自动提交,如果设置为 true,那么不需要手动提交事务
      // 获得 session 会话对象
      SqlSession sqlSession = sqlSessionFactory.openSession();
    • SqlSession 会话对象

      • 执行语句的方法

        // 查询单个对象
        T selectOne(String statement, Object parameter);
        // 查询全部
        List<E> selectList(String statement, Object parameter);
        // 插入
        int insert(String statement, Object parameter);
        // 修改
        int update(String statement, Object parameter);
        // 删除
        int delete(String statement, Object parameter);
      • 操作事务的方法

        void.commit();     // 事务提交
        void rollback(); // 事务回滚
  8. MyBatis DAO 层实现

    • 代理开发方式

      UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
      • Mapper 接口开发需要遵循以下规范

        1. Mapper.xml 文件中的 namespace 与 mapper 接口的全限定名相同
        2. Mapper 接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同
        3. Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同
        4. Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同
  9. MyBatis 映射文件深入

    • 动态 sql —— if

      <select id="findByCondition" resultType="user" parameterType="user">
          select * from user
          <where>
              <if test="id!=0">
                  id=#{id}
              </if>
              <if test="username!=null">
                  and username=#{username}
              </if>
              <if test="password!=null">
                  and password=#{password}
              </if>
          </where>
      </select>
    • 动态 sql —— foreach

      <select id="findByIds" parameterType="list" resultType="user">
          select * from user
          <where>
              <foreach collection="list" open="id in(" close=")" item="id" separator=",">
                  #{id}
              </foreach>
          </where>
      </select>
    • 动态 sql —— sql 语句的抽取

      <!-- sql 语句的抽取 -->
      <sql id="selectUser">select * from user</sql>
      
          <include refid="selectUser"></include>
  10. MyBatis 核心配置文件深入

    • typeHandlers 标签

      • 开发步骤

        1. 定义转换类继承类 BaseTypeHandler<T> 
        2. 覆盖 4 个未实现的方法,其中 setNonNullParameter 为 java 程序设置数据到数据库的回调方法,getNullableResult 为查询时 mysql 的字符串类型转换成 java 的 Type 类型的方法
        3. 在 MyBatis 核心配置文件中个进行注册
        4. 测试转换是否正确
    • plugins 标签

      • 开发步骤

        1. 导入通用 PageHelper 的坐标
        2. 在 mybatis 核心配置文件中配置 PageHelper 插件
        3. 测试分页数据获取
  11. MyBatis 多表操作

    1. 一对一

      • 第一种配置
     

     ```xml
     <resultMap id="orderMap" type="order">
         <!-- 手动指定字段与实体的映射关系
              column: 数据表的字段名称
              property: 实体的属性名称
          -->
         <id column="oid" property="id"/>
         <result column="ordertime" property="orderTime"/>
         <result column="total" property="total"/>
         <result column="uid" property="user.id"/>
         <result column="username" property="user.username"/>
         <result column="password" property="user.password"/>
         <result column="birthday" property="user.birthday"/>
     </resultMap>
     
     <select id="findAll" resultMap="orderMap">
         select *, o.id oid from orders o, user u where o.id=u.id
     </select>
     ```

   - 第二种配置

     ```xml
     <resultMap id="orderMap" type="order">
         <!-- 手动指定字段与实体的映射关系
              column: 数据表的字段名称
              property: 实体的属性名称
          -->
         <id column="oid" property="id"/>
         <result column="ordertime" property="orderTime"/>
         <result column="total" property="total"/>
         <!--<result column="uid" property="user.id"/>
         <result column="username" property="user.username"/>
         <result column="password" property="user.password"/>
         <result column="birthday" property="user.birthday"/>-->
     
         <!--
             property: 当前实体的属性名称
             javaType: 当前实体中的属性的类型
         -->
         <association property="user" javaType="user">
             <id column="uid" property="id"/>
             <result column="username" property="user.username"/>
             <result column="password" property="user.password"/>
             <result column="birthday" property="user.birthday"/>
         </association>
     </resultMap>
     
     <select id="findAll" resultMap="orderMap">
         select *, o.id oid from orders o, user u where o.id=u.id
     </select>
     ```

2. 一对多

   - ```xml
     <resultMap id="userMap" type="user">
         <id column="id" property="id"/>
         <result column="username" property="username"/>
         <result column="password" property="password"/>
         <result column="birthday" property="birthday"/>
     
         <!-- 配置集合信息
              property: 集合名称
              ofType: 当前集合中的数据类型
          -->
         <collection property="orderList" ofType="order">
             <id column="oid" property="id"/>
             <result column="ordertime" property="orderTime"/>
             <result column="total" property="total"/>
         </collection>
     </resultMap>
     
     <select id="findAll" resultMap="userMap">
         select *, o.id oid from user u, order o where u.id=o.uid
     </select>
     ```

3. 多对多

   - ```xml
     <resultMap id="userRoleMap" type="user">
         <id column="userId" property="id"/>
         <result column="username" property="username"/>
         <result column="password" property="password"/>
         <result column="birthday" property="birthday"/>
         
         <collection property="roleList" ofType="role">
             <id column="roleId" property="id"/>
             <result column="roleName" property="roleName"/>
             <result column="roleDesc" property="roleDesc"/>
         </collection>
     </resultMap>
     
     <select id="findUserAndRoleAll" resultMap="userRoleMap">
         select * from user u, sys_user_role ur, sys_role r where u.id=ur.userId and ur.roleId
     </select>
     ```
  1. MyBatis 注解开发

    • 常用注解

      • @Insert:实现新增
      • @Update:实现更新
      • @Delete:实现删除
      • @Select:实现查询
      • @Result:实现结果集封装
      • @Results:可以与 @Result 一起使用,封装多个结果集
      • @One:实现一对一结果封装
      • @Many:实现一对多结果集封装
    • 简单查询

      package com.mapper;
      
      import com.domain.User;
      import org.apache.ibatis.annotations.Delete;
      import org.apache.ibatis.annotations.Insert;
      import org.apache.ibatis.annotations.Select;
      import org.apache.ibatis.annotations.Update;
      
      import java.util.List;
      
      public interface UserMapper {
      
          @Insert("insert into user values(#{id}, #{username}, #{password}, #{birthday})")
          void save(User user);
      
          @Delete("delete from user where id=#{id}")
          void delete(int id);
      
          @Update("update user set username=#{username}, password=#{password} where id=#{id}")
          void update(User user);
      
          @Select("select * from user where id=#{id}")
          User findById(int id);
      
          @Select("select * from user")
          List<User> findAll();
      
      }
      <!-- 加载映射关系 -->
      <mappers>
          <!-- 指定一个包下的接口 -->
          <package name="com.mapper"/>
      </mappers>
    • 复杂查询 —— 一对一

      两种方式:

      • package com.mapper;
        
        import com.domain.Order;
        import org.apache.ibatis.annotations.Result;
        import org.apache.ibatis.annotations.Results;
        import org.apache.ibatis.annotations.Select;
        
        import java.util.List;
        
        public interface OrderMapper {
        
            @Select("select *, o.id oid from orders o, user u where o.id=u.id")
            @Results({
                    @Result(column = "oid", property = "id"),
                    @Result(column = "ordertime", property = "orderTime"),
                    @Result(column = "total", property = "total"),
                    @Result(column = "uid", property = "user.id"),
                    @Result(column = "username", property = "user.username"),
                    @Result(column = "password", property = "user.password")
            })
            List<Order> findAll();
        
        }
      • @Select("select * from orders")
        @Results({
                @Result(column = "id", property = "id"),
                @Result(column = "ordertime", property = "orderTime"),
                @Result(column = "total", property = "total"),
                @Result(
                        javaType = User.class,  // 要封装的实体类型
                        column = "uid",            // 根据哪个字段去查询 user 表的数据
                        property = "user",       // 要封装的属性名
                        // select 属性 代表查询哪个接口的方法获得数据
                        one = @One(select = "com.mapper.UserMapper.findById")
                )
        })
        List<Order> findAll();
    • 复杂查询——一对多

      @Select("select * from orders where uid=#{uid}")
      List<Order> findByUid(int uid);
      @Select("select * from user")
      @Results({
              @Result(id = true, column = "id", property = "id"),
              @Result(column = "username", property = "username"),
              @Result(column = "password", property = "password"),
              @Result(
                      javaType = List.class,  // 要封装的实体类型
                      column = "id",            // 根据哪个字段去查询 user 表的数据
                      property = "orderList",       // 要封装的属性名
                      // select 属性 代表查询哪个接口的方法获得数据
                      many = @Many(select = "com.mapper.OrderMapper.findByUid")
              )
      })
      List<User> findUserAndOrderAll();
    • 复杂查询 —— 多对多