• (二)MyBatis延迟加载,一级缓存,二级缓存


    延迟加载配置:

    什么时候用延迟加载?比如现在有班级和学生表,一对多关系,你可能只需要班级的信息,而不需要该班级学生的信息,这时候可以进行配置,让查询时先查询到班级的信息,在之后需要学生信息时候,再进行查询,避免不必要的查询。

    需要进行如下配置:这里以一对多为例,其他关系类似:

    PersonMapping.xml

        <select id="selectPersonByClassId" resultMap="class_person_map" parameterType="int">
            select * from class where classId=#{id}
        </select>
        <resultMap id="class_person_map" type="class">
            <id column="classId" property="classId"/>
            <result property="number" column="number"/>
            <collection property="persons" ofType="person" select="mappers.ClassMapper.queryPersonByClassId" column="classId">
            </collection>
        </resultMap>

    注意我们的映射,只映射了班级id和班级Number两个信息,并没有映射学生信息,而是通过<cllection>来配置的,标签属性

    select:当需要persons属性时,执行select值所对应的id的sql语句进行查询(mappers.ClassMapper,xml)

    column:执行sql语句时传入的参数

    mappers.ClassMapper.xml

    当需要班级学生信息时,会通过select属性来寻找到指定id的sql语句查询,如下

        <select id="queryPersonByClassId" parameterType="int" resultType="Person">
            select * from person where classId=#{classid}
        </select>

    之后设置断点调试可以看到只有调用了Class.getPersons()方法才会执行查询学生的sql语句。

    一级缓存:

    当通过一个SqlSession对象查询到一个数据时,MyBatis会将该数据放入该sqlsession当中,当下一次再次查询该数据时,会从该sqlsession直接取得该数据,不需要再与数据库交互查询,自动开启。不过注意第二次查询必须也是在同一个SQLSESSION之下进行的。

    二级缓存:

    myBatis内置的:

    接上面,通过一个SQLSession对象查询到了一个数据,不仅会放入一级缓存,还会放入二级缓存当中。当你下一次通过另一个不同的SQLSEssion对象查询相同的数据时,会从二级缓存当中进行获取,不过查询时SQLSession必来自同一个mapper.class。

    总的来说两句话:一级缓存同一个sqlsession,二级缓存同一个mapper.class初始化的,即同一个namespace,是否进入缓存就是依据这个判断的。

    开启配置方式:

    config.xml:

    <setting name="cacheEnabled" value="true"/>

    mapper,xml

    <cache/>

    另外二级缓存是将数据进行序列化的,所以必要要让开启二级缓存的对象继承序列化接口才行。序列化就是将数据从内存放入到硬盘之中。

    即给mapper.xml对应的指定class  加上

    implements Serializable

    而且如果当前mapper对应的class继承了其他类或者里面有级联属性,其他类或者级联属性也必须要序列化。

    相当于序列化三个:本类,父类,级联属性  

    一级缓存二级缓存的缓存时机:

    一级缓存只要查询了就放入一级缓存当中,相当于是实时的,

    二级缓存是在一个sqlsession.close()之后才会将该sqlsession所查询到的放入到二级缓存当中。

    示例:

            //加载配置信息
            Reader reader = Resources.getResourceAsReader("config.xml");
            //connection
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
         //第一个sqlsession SqlSession sqlSession
    = sessionFactory.openSession(); PersonMapping personMapping = sqlSession.getMapper(PersonMapping.class); personMapping.selectPersonById(2); System.out.println("---"); sqlSession.close();
         //第二个sqlsession SqlSession sqlSession2
    = sessionFactory.openSession(); PersonMapping personMapping2 = sqlSession2.getMapper(PersonMapping.class); personMapping2.selectPersonById(2); sqlSession2.close();

    执行后,查看日志可以看到只执行了一条sql语句,PersonMapping.class共享同一个二级缓存

    清理缓存:commit()会清除缓存(一级二级都是的),另外注意这个commit()不能是查询自身的commit,即这个commit所属于的sqlsession对象必须是执行了增删改的sqlsession。

     

  • 相关阅读:
    6、linux中同步、互斥、阻塞(原子操作、信号量、阻塞)
    lightOJ-1199 Partitioning Game (SG函数)
    HDU-1013 Digital Roots
    HDU-1004 Let the Balloon Rise (STL map)
    HDU-1020 Encoding (字符串)
    POJ-2524 Ubiquitous Religions (并查集)
    POJ-1988 Cube Stacking (带权并查集)
    POJ-2236 Wireless Network (并查集)
    HDU-1002 A + B Problem II (模拟大数相加)
    HDU-1829 A Bug's Life (种类并查集)
  • 原文地址:https://www.cnblogs.com/eenio/p/11329269.html
Copyright © 2020-2023  润新知