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