MyBatis 进阶知识

作者: 右耳菌 | 来源:发表于2022-04-13 00:12 被阅读0次

面对复杂的ER关系的情况

  • 如有以下三个实体类

    • 学员 User
    • 课程 Course
    • 教员 Teacher
  • 其中这三者的关系如下ER图所示:


    ER图
  • 数据库表字段和关系图如下所示


    数据库表字段及关系图
  • User 对象

package cn.lazyfennec.entity;

import java.util.List;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/4/12 22:03
 */
public class User {

    private Integer id;
    private String userName;
    private String corp;
    private List<Course> courses;

    public User(Integer id, String userName, String corp) {
        this.id = id;
        this.userName = userName;
        this.corp = corp;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getCorp() {
        return corp;
    }

    public void setCorp(String corp) {
        this.corp = corp;
    }

    public List<Course> getCourses() {
        return courses;
    }

    public void setCourses(List<Course> courses) {
        this.courses = courses;
    }
}

  • Course对象
package cn.lazyfennec.entity;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/4/12 22:04
 */
public class Course {

    private int id;
    private String courseName;
    private Teacher teacher;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
}

  • Teacher对象
package cn.lazyfennec.entity;

/**
 * @Author: Neco
 * @Description:
 * @Date: create in 2022/4/12 22:06
 */
public class Teacher {
    private int id;
    private String teacherName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTeacherName() {
        return teacherName;
    }

    public void setTeacherName(String teacherName) {
        this.teacherName = teacherName;
    }
}

以上三个类有以下三种关系:

  • 关联
  • 容器
  • 嵌套

为了解决如以上三个对象一样的复杂关系,我们需要用到ResultMap

ResultMap相关知识
  1. ResultMap 元素是MyBatis中最重要的最强大的元素。
  2. 数据库永远不是你想要的或需要它们是什么样的。
  3. ResultMap 可以实现复杂查询结果到复杂对象关联关系的转化。
  • ResultMap的一些配置内容
    • Constructor

      • 类在实例化时,用来注入结果到构造方法中
        • idArg - ID参数;标记结果作为ID可以帮助提高整体性能效率。
        • arg - 注入到构造方法的一个普通结果
      • 例子:
      <?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="cn.lazyfennec.mapper.UserMapper">
      
         <select id="getUserById" resultMap="UserMap" parameterType="int">
             select id, userName, corp from user where id = #{id}
         </select>
      
         <resultMap type="cn.lazyfennec.entity.User" id="UserMap">
             <constructor>
                 <idArg column="id" javaType="Integer"/>
                 <arg column="userName" javaType="String"/>
                 <arg column="corp" javaType="String"/>
             </constructor>
         </resultMap>
      </mapper>
      
      • 对应的java执行代码
      package cn.lazyfennec;
      
      import cn.lazyfennec.entity.User;
      import cn.lazyfennec.mapper.UserMapper;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      
      import java.io.InputStream;
      
      /**
       * @Author: Neco
       * @Description:
       * @Date: create in 2022/4/12 22:48
       */
      public class HelloMyBatis {
      
          public static void main(String[] args) {
              // 1.声明配置文件目录读取
              String resource = "mybatis-conf.xml";
              // 2.加载应用配置文件
              InputStream inputStream = HelloMyBatis.class.getClassLoader().getResourceAsStream(resource);
              // 3.创建SqlSessionFactory
              SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              // 4. 获取Session
              SqlSession sqlSession = sessionFactory.openSession();
              try {
                  // 5.获取操作类
                  UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                  // 6. 完成查询操作
                  User user = userMapper.getUserById(9);
                  System.out.println(user.getId() + " " + user.getUserName() + " " + user.getCorp());
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  // 7.关闭session
                  if(sqlSession!=null) sqlSession.close();
              }
          }
      }
      
    • Collection

      • 实现一对多的关联
        • id - 一个ID结果;标记结果作为ID可以帮助提高整体效能
        • result - 注入到字段或 JavaBean 属性的普通结果
      • Mapper.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="cn.lazyfennec.mapper.UserMapper">
      
          <select id="getUserById" resultMap="UserMap" parameterType="int">
              select
                     u.id, userName, corp, c.id courseId, c.courseName
              from user u
                  left join usercourse uc on u.id = uc.user_id
                  left join course c on uc.course_id = c.id
              where u.id = #{id}
          </select>
      
          <resultMap type="cn.lazyfennec.entity.User" id="UserMap">
              <constructor>
                  <idArg column="id" javaType="Integer"/>
                  <arg column="userName" javaType="String"/>
                  <arg column="corp" javaType="String"/>
              </constructor>
              <collection property="courses" ofType="cn.lazyfennec.entity.Course">
                  <id property="id" column="courseId"/>
                  <result property="courseName" column="courseName"/>
              </collection>
          </resultMap>
      
      </mapper>
      
      • 对应的Java代码
      public static void main(String[] args) {
          // 1.声明配置文件目录读取
          String resource = "mybatis-conf.xml";
          // 2.加载应用配置文件
          InputStream inputStream = HelloMyBatis.class.getClassLoader().getResourceAsStream(resource);
          // 3.创建SqlSessionFactory
          SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
          // 代码方式加载UserMapper
          Configuration configuration = sessionFactory.getConfiguration();
          configuration.addMapper(UserMapper.class);
          // 4. 获取Session
          SqlSession sqlSession = sessionFactory.openSession();
          try {
              // 5.获取操作类
              UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
              // 6. 完成查询操作
              User user = userMapper.getUserByAnnotation(9);
              System.out.println(user.getId() + " " + user.getUserName() + " " + user.getCorp());
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              // 7.关闭session
              if(sqlSession!=null) sqlSession.close();
          }
      }
      
    • Association

      • 实现复杂类型之间的关联
        • id - 一个ID结果;标记结果作为ID可以帮助提高整体效能
        • result - 注入到字段或 JavaBean 属性的普通结果
      • Mapper.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="cn.lazyfennec.mapper.UserMapper">
      
          <select id="getUserById" resultMap="UserMap" parameterType="int">
              select
                     u.id, userName, corp, c.id courseId, c.courseName, t.id teacherId, t.teacherName
              from user u
                  left join usercourse uc on u.id = uc.user_id
                  left join course c on uc.course_id = c.id
                  left join teacher t on c.teacher_id = t.id
              where u.id = #{id}
          </select>
      
          <resultMap type="cn.lazyfennec.entity.User" id="UserMap">
              <constructor>
                  <idArg column="id" javaType="Integer"/>
                  <arg column="userName" javaType="String"/>
                  <arg column="corp" javaType="String"/>
              </constructor>
              <collection property="courses" ofType="cn.lazyfennec.entity.Course">
                  <id property="id" column="courseId"/>
                  <result property="courseName" column="courseName"/>
                  <association property="teacher" column="teacher_id" javaType="cn.lazyfennec.entity.Teacher">
                      <id property="id" column="teacherId"/>
                      <result property="teacherName" column="teacherName"/>
                  </association>
              </collection>
          </resultMap>
      </mapper>
      
      • 对应的Java代码
      public static void main(String[] args) {
          // 1.声明配置文件目录读取
          String resource = "mybatis-conf.xml";
          // 2.加载应用配置文件
          InputStream inputStream = HelloMyBatis.class.getClassLoader().getResourceAsStream(resource);
          // 3.创建SqlSessionFactory
          SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
          // 4. 获取Session
          SqlSession sqlSession = sessionFactory.openSession();
          try {
              // 5.获取操作类
              UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
              // 6. 完成查询操作
              User user = userMapper.getUserById(9);
              System.out.println(user.getId() + " " + user.getUserName() + " " + user.getCorp());
              System.out.println("courses: ");
              for (Course course : user.getCourses()) {
                  System.out.println(">>> "
                          + "id:" + course.getId()
                          + " courseName:" + course.getCourseName()
                          + " teacherId: " + course.getTeacher().getId()
                          + " teacherName: " + course.getTeacher().getTeacherName());
      
              }
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              // 7.关闭session
              if (sqlSession != null) sqlSession.close();
          }
      }
      

数据库连接池 DataSource

  • MyBatis 3.0 内置连接池
  • dataSource type = POOLED 启用连接池
<dataSource type="POOLED">
MyBatis数据库连接声明周期
  • 连接池常用配置选项
    • poolMaximumActiveConnections
      • 数据库最大活跃连接数
      • 考虑到随着连接数的增加,性能可能会达到拐点,不建议设置过大
    • poolMaximumIdleConnections
      • 最大空闲连接数
      • 建议设置与poolMaximum相同即可
    • poolMaximumCheckoutTime
      • 获取连接时如果没有idleConnection同时activeConnection也达到最大值,则从activeConnections列表第一个连接开始,检查是否超过poolMaximumCheckoutTime,如果超过,则强制使其失效,返回该连接。即使该连接断开,并返回到连接池中
      • 由于SQL执行时间受服务器配置、表结构不通,建议设置为预期最大SQL执行时间。如2分钟,3分钟等,以提高获取数据库连接的效率。
    • poolTimeToWait
      • 获取服务器端数据库连接的超时时间,如果超过该时间,则打印日志,同时重新获取。
      • 建议使用默认值20s
    • poolPingEnabled
      • 启用连接侦测,检查连接池中的连接是否为有效连接。
      • 默认关闭,建议启用,防止服务器端异常关闭连接,导致客户端错误。
    • poolPingQuery
      • 侦测SQL,建议使用select 1,开销小
    • poolPingConnectionsNotUsedFor
      • 侦测时间,建议小于服务器超时时间,MySQL默认超时时间8小时(即服务器连接空闲超过八小时,服务器自动关闭该连接,但是如果不启用侦测,则客户端无法发现连接已经失效)

更多内容建议查看官网

点击右方链接查看官方文档:https://mybatis.org/mybatis-3/zh/index.html

相关文章

网友评论

    本文标题:MyBatis 进阶知识

    本文链接:https://www.haomeiwen.com/subject/mxgnsrtx.html