Mybatis中的延迟加载
-
问题:在一对多中,当我们有一个用户,它有100个账户。
在查询用户的时候,要不要把关联的账户查出来?
在查询账户的时候,要不要把关联的用户查出来?
事实上,在查询用户时,用户下的账户信息应该是,什么时候使用,什么时候查询的。
在查询账户时,账户的所属用户信息应该是随着账户查询时一起查询出来。 -
延迟加载:在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)
-
立即加载:不管用不用,只要一调用方法,马上发起查询。
-
在对应的四种表关系中:一对多,多对一,一对一,多对多
一对多,多对多:通常情况下我们都是采用延迟加载。
多对一,一对一:通常情况下我们都是采用立即加载。 -
延时加载使用方法
在SqlMapConfig.xml中设置
<!-- 开启延迟加载的支持 -->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
之后在相应的映射关系对象配置时,引入select
属性,属性的值配置对应的延时加载要调用的语句,例如:
<!-- 配置user对象中accounts集合的映射 -->
<collection property="accounts" ofType="account" select="cn.whd.dao.AccountDao.findAccountByUid" column="id"></collection>
<collection>
说明这个映射关系为对多的关系,是集合,ofType为该集合的保存类型,select为延时加载要调用的SQL语句对应的配置信息位置
Mybatis中的缓存
- 缓存存在于内存中的临时数据。
- 使用缓存可以减少和数据库的交互次数,提高执行效率。
- 适用于缓存的数据:
经常查询并且不经常改变的。
数据的正确与否对最终结果影响不大的。 - 不适用于缓存的数据:
经常改变的数据
数据的正确与否对最终结果影响很大的。
例如:商品的库存,银行的汇率,股市的牌价。 - Mybatis中的一级缓存和二级缓存
-
一级缓存:指的是Mybatis中SqlSession对象的缓存。
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。
该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。
当调用SqlSession对象的修改,添加,删除,commit(),close()等方法后,mybatis的一级缓存也就消失了。
同时SqlSession.clearCache()
方法也可以清空缓存 -
二级缓存:指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
- 二级缓存的使用步骤:
- 让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
<settings> <setting name="cacheEnabled" value="true"/> </settings>
- 让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
<!--开启user支持二级缓存--> <cache/>
- 让当前的操作支持二级缓存(在select标签中配置useCache属性)
<select useCache="true"> </select>
- 二级缓存中存放的是数据,而不是对象
-
Mybatis中的注解开发
- 注意:使用注解开发时,不能存在对应的.xml配置文件,否则会报错
- 注解开发与xml开发大同小异
注解开发使用@Select,@Update,@Delete,@Insert书写SQL语句
使用@Result,@Results,@ResultMap封装结果集
使用@One实现一对一结果集封装
使用@Many实现一对多结果集封装
使用@CacheNamespace实现注解二级缓存的使用 - 实现一对一的注解开发
//查询所有账户
@Select("select * from account")
@Results(id="accountMap",value = { //id属性为该映射集起名,之后的其他语句也可以直接使用此映射集
@Result(id=true,column = "id",property = "id"), //将id属性设为true代表这是主键
@Result(column = "uid",property = "uid"),
@Result(column = "money",property = "money"),
@Result(property = "user",column = "uid",one=@One(select="cn.whd.dao.UserDao.findById",fetchType= FetchType.EAGER))
//one属性引用@one注解,其中select代表对应的SQL语句,fetchType代表加载方式(延时加载或立即加载)
})
List<Account> findAll();
- 实现一对多的注解开发
//查询所有用户
@Select("select * from user")
@Results(id="userMap",value={
@Result(id=true,column = "id",property = "userId"),
@Result(column = "username",property = "userName"),
@Result(column = "address",property = "userAddress"),
@Result(column = "sex",property = "userSex"),
@Result(column = "birthday",property = "userBirthday"),
@Result(property = "accounts",column = "id",
many = @Many(select = "cn.whd.dao.IAccountDao.findAccountByUid",
fetchType = FetchType.LAZY))
})
List<User> findAll();
//根据id查询用户
@Select("select * from user where id=#{id} ")
@ResultMap("userMap") //使用上面已经定义的ResultMap
User findById(Integer userId);
Mybatis中注解开发使用二级缓存
- 首先在SqlMapConfig.xml中配置
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
- 然后在对应的dao接口上添加
@CacheNamespace(block=true)
注解,即可开启二级缓存