开发者

mybatis 查询方式与效率高低对比

开发者 https://www.devze.com 2023-03-16 10:32 出处:网络 作者: 遇见的昨天
目录myBATis查询方式与效率高低mybatis提高查询效率的方式缓存机制懒加载总结mybatis查询方式与效率高低
目录
  • myBATis查询方式与效率高低
  • mybatis提高查询效率的方式
    • 缓存机制
    • 懒加载
  • 总结

    mybatis查询方式与效率高低

    <!--
      一对一关联查询
      select s.id,s.name,s.age,t.name tname from student s,teacher t where s.tid=t.id;
       -->
    
      <!--
        关联的嵌套 Select 查询
      问题:
        这种方式虽然很简单,但在大型数据集或大型数据表上表现不佳。这个问题被称为“N+1 查询问题”。 概括地讲,N+1 查询问题是这样子的:
          你执行了一个单独的 SQL 语句来获取结果的一个列表(就是“+1”)。
          对列表返回的每条记录,你执行一个 select 查询语句来为每条记录加载详细信息(就是“N”)。
      解决:
        MyBatis 能够对这样的查询进行延迟加载,因此可以将大量语句同时运行的开销分散开来。
        (例如: 我需要teacher这个对象的时候就会进行加载,如果不需要就不会立即加载(延迟加载))
        然而,如果你加载记录列表之后立刻就遍历列表以获取嵌套的数据,就会触发所有的延迟加载查询,性能可能会变得很糟糕。
      -->
      <!-- 关联的嵌套 Select 查询 -->
      <resultMap id="studentMap" type="student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="a编程客栈ge" column="age"/>
        <association property="teacher" col编程umn="tid" JavaType="teacher" select="selectTeacherById">
        </association>
      </resultMap>
    
      <select id="findAll" resultMap="studentMap">
        select * from student;
      </select>
      <select id="selectTeacherById" parameterType="int" resultType="teacher" >
        select * from teacher where id=#{id};
      </select>
    
    
      <!--
        关联的嵌套 结果映射
      将结果直接映射 到实体类中
        第二种 方式效率比第一种 速度更高
      -->
      <resultMap id="studentMap1" type="student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="age" column="age"/>
        <association property="teacher" javaType="teacher">
          <id property="id" column="tid"/>
          <result property="name" column="tname"/>
        </association>
      </resultMap>
      <select id="selectAll" resultMap="studentMap1">
        select s.id,s.name,s.age,t.name tname ,t.id tid fpythonrom student s,teacher t where s.tid=t.id;
      </select>
    
    ------------------------------------------------------------------
    <!-- 一对多 关联嵌套 结果映射  ofType 将数据封装到指定的泛型 -->
      <resultMap id="teacherMap" type="teacher">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="students" ofType="student" >
          <id property="编程客栈id" column="sid"/>
          <result property="name" column="sname"/>
          <result property="age" column="sage"/>
          <result property="tid" column="stid"/>
        </collection>
      </resultMap>
      <select id="selectTeacherById" parameterType="int" resultMap="teacherMapphp">
        select t.id ,t.name,s.id sid,s.name sname,s.age sage,s.tid stid
        from student s ,teacher t
        where s.tid=t.id and t.id=1;
      </select>
    

    mybatis提高查询效率的方式

    缓存机制

    1 一级缓存:

    当mysql连续执行两次select * from table where id =1;第一次会执行sql语句查询数据库,然后保存到sqlsess开发者_Go培训ion缓存,第二次查询会先从缓存里查找,有的话直接返回不会执行sql.

    但是如果两次sql中间增加一次commit操作(insert,delete,update),如:

    select * from table where id =1
    update table set name = zjw where id =1;
    select * from table where id =1

    这个时候第一次查询依然会执行sql查询数据库,但是在执行完update后会清空sqlsession里的缓存,原因是避免脏读,

    所以第二次select在缓存里找不到数据,又会执行sql查询数据库。

    2 二级缓存:

    二级缓存是基于mapper文件的namASPace,对该mapper的所有sqlsession都共享一个二级缓存,如果两个mapper的namespace一致,则两个mapper的所有sqlsession共用一个二级缓存,

    步骤:

    在全局配置文件mybatis-configuration.XML加入

    其次在mapper文件开启缓存 type里面是缓存类。如果不写是默认的mabatis缓存类,自定义缓存类必须实现cache接口

    需要缓存的pojo实体类要实现serializable接口,因为在缓存中取出数据映射到pojo类需要反序列化。

    不同的两个sqlsession查询走二级缓存,但是如果其中有一个commit操作,为避免脏读二级缓存还是会被清空。

    在每个sql语句上使用useCache=true/false是否使用缓存,flushcache=true/false是否刷新缓存 ,在每次的commit后默认刷新缓存。

    懒加载

    Mybatis中resultmap可以实现高级映射,association一对一,Collection一对多具有延迟加载功能

    在collection或association中fetchtype=lazy,即为懒加载

    在查询主表时,不会把子集查出来,直到子集用到的情况才会查出子集。

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号