03_Mybatis

本文深入探讨MyBatis框架的高级特性,包括事务控制、缓存机制、动态SQL、多表关联查询及延迟加载策略。通过具体示例,解析如何优化数据库交互,提升应用程序性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

03_Mybatis

Mybatis事务控制

工程准备:新建一个Maven类型的module:实现Mybatis保存用户功能,便于基于该功能的代码程序说明Mybatis的事务控制

SqlMapConfig.xml中配置的type=“JDBC”:使用Jdbc的事务管理机制,connection的事务

Mybatis默认把Jdbc的事务自动提交给关闭了

Mybatis缓存

缓存只能对的是CRUD中的R(查询)

缓存需要进行维护(数据发生变化的时候,需要维护缓存),这样才能保持数据的一致性

工程准备:实现Mybatis根据id查询用户功能,便于基于该功能的代码程序说明Mybatis缓存

概述

网站性能优化第一定律:优先使用缓存机制(分布式redis缓存)。

Mybatis中的缓存

​ Mybatis提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。

​ Mybatis中缓存分为一级缓存,二级缓存。Mybatis的二级缓存机制存在诸多问题。无法在企业中开发中应用。

​ Mybatis的一级缓存是SqlSession级别(在同一个SqlSession持续期间有效)的缓存,是默认开启的

  @Test
    public void testQueryUserOrders() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
 <!--一级缓存是SqlSession级别的,同一个SqlSession范围内执行相同的sql语句,会走一级缓存--> 
        sqlSession.close();

    }

结果分析

​ 虽然上面的代码我们查询中写了两次,但是只执行了一次数据库查询操作,这就是Mybatis提供给我们的一级缓存起作用了

​ 因为一级缓存的存在,导致第二次查询同一id的记录是(同一条sql),并没有发出sql语句从数据库中查询数据,而是从一级缓存中查询

​ 第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库中查询信息。得到用户信息,将用户信息存储到一级缓存中,

​ 如果sqlSession去执行commit操作(执行插入,更新,删除),清空sqkSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

​ 一级缓存是SqlSession范围的缓存,当调用sqlSession的修改,添加,删除,commit(),close()等方法时候,就会清空一级缓存

Mybatis映射文件的Sql深入(动态sql机制)

优雅的帮助我们拼接sql语句(主要是标签是使用)

需求:根据用户性别和用户名称查询用户列表

if标签/where标签

   List<User>  queryUserByWhere(User user) throws Exception;
<!--根据用户性别和用户名查询user ,拼接sql语句的方式-->
    <select id="queryUserByWhere" parameterType="user" resultType="user">
        SELECT * FROM USER
        <where><!--where会自动添加where关键字并且干掉紧接着的第一个and关键字或者or关键字-->
            <!--if标签会帮我们进行判断,test判断表达式的真假-->
            <if test="sex != null and sex != '' ">
                AND sex = #{sex}
            </if>
            <if test="username != null and username != ''">
                AND username=#{username}
            </if>
        </where>
    </select>
/**
     *使用if标签和where标签 动态SQL语句 拼接sql语句
     */
    @Test
    public void testQueryUserByWhere() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
//        user.setUsername("张三");
        user.setSex("1");
        List<User> users = mapper.queryUserByWhere(user);
        for (int i = 0; i < users.size(); i++) {
            User user1 =  users.get(i);
            System.out.println(user);
        }

        sqlSession.close();
    }

sql片段

<!--
        sql片段
        引用sql片段使用include标签,refid 只想sql片段的id 如果共享其他的mapper文件当中的sql片段,
        只要在refid前面加上另一个mapper映射文件的namespace即可
    -->
    <sql id="commentSql">
         id,username,sex,birthday,address
    </sql>

foreach标签

List<User> queryUserByIdsList(List<Integer> list)throws Exception;
 <select id="queryUserByIdsList" parameterType="list" resultType="user">
        SELECT <include refid="commentSql"></include> FROM USER
        <foreach collection="list" open="where id in(" close=")" separator="," item="item">
            #{item}
        </foreach>
    </select>
   /**
     * 根据多个id来查询用户列表
     */
    @Test
    public void testQueryUserByIdsList() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<Integer> list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        List<User> users = userMapper.queryUserByIdsList(list);
        for (int i = 0; i < users.size(); i++) {
            User user =  users.get(i);
            System.out.println(user);
        }

        sqlSession.close();

    }

Mybatis的多表关联查询

多表关系分析

多表:至少2两张表

多表关系分析技巧:盯着一张表A的一条记录,从这一条记录出发,看这条记录在另外一张表B中可能有几条关联记录,如果只会有一条关联记录,那么从A到B就是一对一,如果可能有多条关联记录,那么从A到B就是一个一对多的关系。

多表关系:

一对一

一对多

User表 orders表

从表中有外键指向主表中的主键

多对多

User role

中间表

Userid roleid

多表关联的SQL语句表达

  1. 笛卡尔积

    select * from user,orders

  2. 笛卡尔积 + where

    select * from user u ,orders o where u.id = o.user_id

  3. 关联查询

    内关联 inner join效果等同于笛卡尔积+where

    外关联

    ​ left join

    ​ right join

一对一查询

Mybatis 帮我们做的事:

  1. sql语句是用户自己写的,Mybatis框架只是帮我们执行
  2. 封装结果集

需求:查询订单表全部数据,关联查询出订单对应的用户数据(username address)

Mapper映射文件
<select id="queryOrdersUser" resultMap="ordersUserResultMap">
    SELECT
      o.`id`,
      o.`user_id`,
      o.`number`,
      o.`createtime`,
      o.`note`,
      u.`username`,
      u.`address`
    FROM
      orders o
      LEFT JOIN user u
        ON o.`user_id` = u.`id`
</select>


<resultMap id="ordersUserResultMap" type="orders">
    <!--两部分数据:订单+用户-->
    <id column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime"/>
    <result column="note" property="note"/>

    <!--association:关联的意思,用于一对一关联封装数据
        property:一对一关联后封装成的数据所对应的属性名
        javaType:属性的类型
    -->
    <association property="user" javaType="user">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
    </association>
</resultMap>

测试程序
@Test
public void testQueryOrdersUser()throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
    List<Orders> ordersList = ordersMapper.queryOrdersUser();
    if(ordersList != null && ordersList.size() > 0) {
        for (int i = 0; i < ordersList.size(); i++) {
            Orders orders =  ordersList.get(i);
            System.out.println(orders);
        }
    }
    sqlSession.close();
}

一对多查询

需求:查询全部用户数据,关联查询出订单数据

Mapper映射文件
<!--一对多用例-->
<select id="queryUserOrders" resultMap="userOrdersResultmap">
    SELECT
      u.`id`,
      u.`username`,
      u.`sex`,
      u.`birthday`,
      u.`address`,
      o.`id` oid,
      o.`user_id`,
      o.`number`,
      o.`createtime`,
      o.`note`
    FROM
      user u
      LEFT JOIN orders o
        ON u.`id` = o.`user_id`
</select>

<resultMap id="userOrdersResultmap" type="user">
    <!--两部分数据:用户+订单-->
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <result column="sex" property="sex"/>
    <result column="birthday" property="birthday"/>
    <result column="address" property="address"/>

    <!--一对多使用collection标签
        property:封装成对应的属性的属性名
        ofType:因为此时属性是一个list集合,collection已经表明了集合的意思,最重要的指定list里面的泛型类型,
        所以使用ofType
    -->
    <collection property="ordersList" ofType="orders">
        <id column="oid" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
    </collection>
</resultMap>

多对多查询

多对多关系分析

实现Role到User的一对多

实现User到Role的一对多

Mybatis延迟加载策略

什么是延迟加载

Mybatis怎么实现Mybatis

了解(不推荐)Mybatis注解开发

使用注解实现基本的CRUD操作

使用注解实现复杂关系映射开发

使用注解实现一对一查询

使用注解实现一对多查询

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值