• Mybatis——Mybatis表之间的关联关系和事务、缓存机制以及ORM


    1. 表之间的关联关系

       我们通常说的关联关系有以下四种,一对多关联,多对一关联,一对一关联,多对多关联。关联关系是有方向的。如果是高并发的场景中,不适合做表的关联。

    1.1 一对多的关联

       在多对一和一对多的关联关系中,使用订单表和客户表来描述问题。

    • 一对多:一个客户可以有多张订单,在查询时注意使用左连接查询,因为我们查询的主体使用户,一个用户可以没有订单,但是他应该显示在结果集中
      实体类创建:
      主要上以下几种方法
    • 无参构造以及包含所有属性的有参构造方法
    • set和get方法
    • toString方法

    在这里插入图片描述

    在这里插入图片描述

    接口代码:

    //根据客户id查询客户所有信息,并同时查询客户的所有订单信息
        Customer getById(Integer id);
    xml文件的查询语句:
    
    • 1
    • 2
    • 3
    <mapper namespace="com.lcl.mapper.CustomerMapper">
    
    
        
        <resultMap id="customermap" type="customer">
            
            <id property="id" column="cid">id>
            
            <result property="name" column="name">result>
            <result property="age" column="age">result>
            
            <collection property="ordersList" ofType="orders">
                
                
                <id property="id" column="oid">id>
                
                <result property="orderNumber" column="orderNumber">result>
                <result property="orderPrice" column="orderPrice">result>
            collection>
        resultMap>
        
        <select id="getById" parameterType="int" resultMap="customermap">
            select c.id cid,name,age,o.id oid,orderNumber,orderPrice,customer_id
            from customer c left join orders o on c.id = o.customer_id
            where c.id = #{id}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    测试方法:

    public class MyTest {
    
        SqlSession sqlSession;
    
        @Before
        public void getSqlSession() throws IOException {
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            sqlSession = factory.openSession();
        }
    
        @After
        public void closeSqlSession(){
            sqlSession.close();
        }
        /*
        根据客户id查询客户所有信息,并同时查询客户的所有订单信息
        Customer getById(Integer id);
        实现的是一对多的查询
        */
        @Test
        public void testCustomerGetById(){
            CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
            Customer customer = customerMapper.getById(3);
            System.out.println(customer);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    1.2 多对一的关联

    • 多个订单属于同一个用户

    接口代码:

    //根据主键查询订单,同时查询此订单下的客户信息
        Orders getById(Integer id);
    
    • 1
    • 2

    xml文件的查询语句:

    <mapper namespace="com.lcl.mapper.OrdersMapper">
    
        
        <resultMap id="ordersmap" type="orders">
            
            <id property="id" column="oid">id>
            
            <result property="orderNumber" column="orderNumber">result>
            <result property="orderPrice" column="orderPrice">result>
            
            <association property="customer" javaType="customer">
                <id property="id" column="cid">id>
                
                <result property="name" column="name">result>
                <result property="age" column="age">result>
            association>
        resultMap>
        <select id="getById" resultMap="ordersmap">
            select o.id oid,orderNumber,orderPrice,customer_id,c.id cid,name,age
            from orders o inner join customer c on customer_id = c.id
            where o.id = #{id}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    测试方法:

    public class MyTest {
    
        SqlSession sqlSession;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    
        @Before
        public void getSqlSession() throws IOException {
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            sqlSession = factory.openSession();
        }
    
        @After
        public void closeSqlSession(){
            sqlSession.close();
        }
        /*
        根据主键查询订单,同时查询此订单下的客户信息
        Orders getById(Integer id);
        实现的是多对一的查询
        */
        @Test
        public void testOrdersGetById(){
            OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
            Orders orders = ordersMapper.getById(11);
            System.out.println(orders);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    1.3 多对多的关联

    • 多对多的查询使用图书和所属类别来描述问题,例如书名时MySQL和Java技术,那么毫无疑问,他就属于MySQl和Java,但是还有其他的书名也属于Java,如Java核心卷
    • 因此一本书可以属于多种类名,而一种类别又可以拥有多本书,所以图书和类别可以说明多对多的问题

    实体类准备:
    主要上以下几种方法

    • 无参构造以及包含所有属性的有参构造方法
    • set和get方法
    • toString方法
      在这里插入图片描述
      在这里插入图片描述
      接口代码:

    在这里插入图片描述
    xml文件的查询语句

    <mapper namespace="com.lcl.mapper.TeacherMapper">
    
        
        <resultMap id="teachermap" type="teacher">
            
            <id property="tid" column="tid">id>
            
            <result property="tname" column="tname">result>
            <result property="tage" column="tage">result>
            
            <association property="classes" javaType="classes">
                <id property="cid" column="cid">id>
                <result property="cname" column="cname">result>
            association>
        resultMap>
        <select id="findTeacherMessage" resultMap="teachermap">
            select tid,tname,tage,cid,cname
            from teacher inner join classes on tid = ctid
        select>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    测试代码:

    public class MyTest {
    
        SqlSession sqlSession;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    
        @Before
        public void getSqlSession() throws IOException {
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            sqlSession = factory.openSession();
        }
    
        @After
        public void closeSqlSession(){
            sqlSession.close();
        }
    
    
        //查询全部图书,并且查询图书所属的全部类型
        //List findAll();
        //实现的时多对多的查询
        @Test
        public void testFindAll(){
            BooksMapper booksMapper = sqlSession.getMapper(BooksMapper.class);
            List<Books> booksList = booksMapper.findAll();
            booksList.forEach(books -> System.out.println(books));
        }
    
        //查询教师全部信息,并且返回教师所教授知识的位置
        //Teacher findTeacherMessage();
        //实现一对一的查询
        @Test
        public void testFindTeacherMessage(){
            TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
            List<Teacher> teacherList = teacherMapper.findTeacherMessage();
            teacherList.forEach(teacher -> System.out.println(teacher));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    1.4 一对一的关联

    • 一对一的关联关系使用的是教师和班级之间的关系来说明问题:一个老师只教授一个班级,一个班级只能被一个教师教授

    实体类创建:
    主要上以下几种方法

    • 无参构造以及包含所有属性的有参构造方法
    • set和get方法
    • toString方法
      在这里插入图片描述
      在这里插入图片描述
      接口中方法定义:
    //查询教师全部信息,并且返回教师所教授知识的位置
        List<Teacher> findTeacherMessage();
    
    • 1
    • 2

    xml文件中查询语句

    <mapper namespace="com.lcl.mapper.TeacherMapper">
    
        
        <resultMap id="teachermap" type="teacher">
            
            <id property="tid" column="tid">id>
            
            <result property="tname" column="tname">result>
            <result property="tage" column="tage">result>
            
            <association property="classes" javaType="classes">
                <id property="cid" column="cid">id>
                <result property="cname" column="cname">result>
            association>
        resultMap>
        <select id="findTeacherMessage" resultMap="teachermap">
            select tid,tname,tage,cid,cname
            from teacher inner join classes on tid = ctid
        select>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    测试代码:

    public class MyTest {
    
        SqlSession sqlSession;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    
        @Before
        public void getSqlSession() throws IOException {
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            sqlSession = factory.openSession();
        }
    
        @After
        public void closeSqlSession(){
            sqlSession.close();
        }
        //查询教师全部信息,并且返回教师所教授知识的位置
        //Teacher findTeacherMessage();
        //实现一对一的查询
        @Test
        public void testFindTeacherMessage(){
            TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
            List<Teacher> teacherList = teacherMapper.findTeacherMessage();
            teacherList.forEach(teacher -> System.out.println(teacher));
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2. Mybatis知识点小结

    2.1 事务

    • Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式有两种,一种是容器进行事务管理的,一种是程序员手工决定事务的提交与回滚。
    • SqlMapConfig.xml文件中设定的事务处理的方式。

    在这里插入图片描述

    • MyBatis 支持两种事务管理器类型:JDBC 与 MANAGED
    • JDBC:使用 JDBC 的事务管理机制。即,通过 Connection 的 commit()方法提交,通过 rollback()方法回滚。但默认情况下,MyBatis 将自动提交功能关闭了,改为了手动提交。即程序中需要显式的对事务进行提交或回滚。从日志的输出信息中可以看到。
    • 在获得SqlSession的时候,如果openSession()是无参或者是false,则必须手工提交事务,如果openSession(true),则为自动提交事务,在执行完增删改后无须commit(),事务自动提交。

    在这里插入图片描述

    2.2 缓存机制

    • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。mybatis提供查询缓存,用于减轻数据库压力,提高数据库性能。

    2.2.1 缓存执行机制

    在进行数据库访问时,首先去访问缓存,如果缓存中有要访问的数据,则直接返回客户端,如果没有则去访问数据库,在库中得到数据后,先在缓存放一份,再返回客户端。如下图。
    在这里插入图片描述

    注意:mybaits提供一级缓存和二级缓存。默认开启一级缓存。

    2.2.2 一级缓存

        第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。如果sqlSession去执行commit操作(执行插入、更新、删除),则清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
        第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。如果没有重复第一次查询操作。如下图。

    在这里插入图片描述

    @Test
    public void testCacheOne() {
        //一级缓存基于SqlSession的
        //取出用户ID为7的用户
        Users u1 = mapper.getById(7);
        System.out.println("第一次访问数据库得到的u=" + u1);
        //再取一次,看看有没有访问数据库,就知道开没有开启一级缓存
        Users u2 = mapper.getById(7);
        System.out.println("第二次访问数据库得到的u=" + u2);
    }
    @Test
    public void testCacheOneClose() {
        //一级缓存基于SqlSession的
        //取出用户ID为7的用户
        Users u1 = mapper.getById(7);
        System.out.println("第一次访问数据库得到的u=" + u1);
        //关闭session,也会清除缓存
        session.close();
        //再取一次,看看有没有访问数据库,就知道开没有开启一级缓存
        session = factory.openSession();
        mapper = session.getMapper(UsersMapper.class);
        Users u2 = mapper.getById(7);
        System.out.println("第二次访问数据库得到的u=" + u2);
    }
    @Test
    public void testCacheOneCommit() {
        //一级缓存基于SqlSession的
        //取出用户ID为7的用户
        Users u1 = mapper.getById(7);
        System.out.println("第一次访问数据库得到的u=" + u1);
    
        //完成数据更新操作
        int num = mapper.update(new Users(38, "abc", new Date(), "1", "朝阳"));
        session.commit();
        System.out.println(num + "==================");
    
        Users u2 = mapper.getById(7);
        System.out.println("第二次访问数据库得到的u=" + u2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.3 ORM

    ORM(Object Relational Mapping):对象关系映射
    MyBatis框架是ORM非常优秀的框架.

    ORM含义描述:java语言中以对象的方式操作数据,存到数据库中是以表的方式进行存储,对象中的成员变量与表中的列之间的数据互换称为映射.整个这套操作就是ORM.

    持久化的操作:将对象保存到关系型数据库中 ,将关系型数据库中的数据读取出来以对象的形式封装

  • 相关阅读:
    Jetson Nano 部署(3):TensorRT介绍
    【RTOS训练营】定时器的机制、源码分析和晚课提问
    linux 系统内存诊断
    面对以太坊合并,投资者有哪些参与策略?
    移远通信C-V2X模组产品 助力车载生态建设跑出“加速度”
    vue 2个接口同步执行
    jquery 获取具体时间(年月日)后3个月+1天的年月日
    学过单片机的都知道,节电器到底能不能省电
    Lua位或操作
    什么是软件测试?
  • 原文地址:https://blog.csdn.net/weixin_44606952/article/details/126617583