延迟加载配置:
什么时候用延迟加载? 比如现在有班级和学生表, 一对多关系, 你可能只需要班级的信息, 而不需要该班级学生的信息, 这时候可以进行配置, 让查询时先查询到班级的信息, 在之后需要学生信息时候, 再进行查询, 避免不必要的查询.
需要进行如下配置: 这里以一对多为例, 其他关系类似:
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.
来源: http://www.bubuko.com/infodetail-3149873.html