Mybatis 延迟加载、缓存、注解
mybatis中的延迟加载
-
Problem:在一对多中,当我们有一个用户,他有100个账户。
- 在查询用户的时候,要不要把关联的账户查出来?
在查询用户时,用户下的账户信息应该是,什么时候使用,什么时候查询的。
- 在查询账户的时候,要不要把关联的用户查出来?
在查询账户时,账户的所属用户信息应该是随着账户查询时一起查询出来。
-
延迟加载:在真正使用数据时才发起查询,不用的时候不查询,按需加载。
-
立即加载:不管用不用,只要一调用方法,马上发起查询。
-
在对应的四种表关系中:一对多,多对一,一对一,多对多
- 一对多,多对多:通常情况下我们都是采用延迟加载。
- 多对一,一对一:通常情况下我们都是采用立即加载。
<!--(SqlMapConfig.xml)配置参数--> <settings> <!--开启mybatis支持延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
<!--一对一关系映射,配置封装user的内容:(user) select属性指定的内容,查询用户的唯一标识 column属性指定的内容,用户根据id查询时,所需要的参数的值 --> <association property="user" column="uid" javaType="user" select="com.ssm.dao.IUserDao.findById"> </association>
<!--一对多关系映射,配置user对象中accounts集合的映射--> <collection property="accounts" ofType="account" select="com.ssm.dao.IAccountDao.findAccountByUid" column="id"></collection>
-
mybatis中的缓存
-
缓存:存在于内存中的临时数据
-
为什么使用缓存:减少和数据库的交互次数,提高执行效率
-
什么样的数据能使用缓存,什么样的数据不能使用
- 适用缓存的:经常查询并且不经常更改,数据的正确与否对最终结果影响并不大的
- 不适用缓存的:经常改变的数据,数据的正确与否对最终结果影响很大的。例如,商品的库存、银行的汇率,股市的牌价
-
mybatis中的一级缓存和二级缓存
- 一级缓存:指的是mybatis中SqlSession对象的缓存。当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供的一块区域中,该区域的结构是一个Map,当我们再次查询同样的数据,mybatis会先去SqlSession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时,mybatis的一级缓存也就消失了。当调用SqlSession的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
//测试一级缓存 @Test public void testFirstLevelCache(){ User user1 = userDao.findById(41); System.out.println(user1); User user2 = userDao.findById(41); System.out.println(user2); System.out.println(user1 == user2); }
测试结果如下:
com.ssm.domain.User@3aeaafa6 com.ssm.domain.User@3aeaafa6 true
@Test public void testFirstLevelCache(){ User user1 = userDao.findById(41); System.out.println(user1); // session.close(); // //重新获取SqlSession对象 // session = factory.openSession(); session.clearCache();//此方法也可以清空缓存 userDao = session.getMapper(IUserDao.class); User user2 = userDao.findById(41); System.out.println(user2); System.out.println(user1 == user2); }
测试结果如下:
com.ssm.domain.User@3aeaafa6 com.ssm.domain.User@4d3167f4 false
-
二级缓存:指的是mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
- 第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
<!--全局开启配置文件中所有映射器已经配置的缓存--> <settings> <setting name="cacheEnabled" value="true"/> </settings>
- 第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
<!--开启user支持二级缓存--> <cache/>
- 第三步:让当前的操作支持二级缓存(在select标签中配置)
<!--根据id查询用户--> <select id="findById" parameterType="int" resultType="user" useCache="true"> SELECT * from USER WHERE id = #{uid} </select>
mybatis中的注解开发
-
环境搭建
- 注意:采用注解开发时就不能在同一个dao下面使用xml
-
单表CRUD操作(代理dao方式)
- 在mybatis中针对CRUD有四个注解:
@Select
、@Insert
、@Update
、@Delete
- 在mybatis中针对CRUD有四个注解:
-
多表查询操作
- 一对多,
id
为true表示为主键
@Select("select * from user") @Results(id = "userMap",value = { @Result(id=true,column = "id",property = "userId"), @Result(column = "address",property = "userAddress"), @Result(column = "username",property = "userName"), @Result(column = "sex",property = "userSex"), @Result(column = "birthday",property = "userBirthday"), @Result(column = "id",property = "accounts", many = @Many( select = "com.ssm.dao.IAccountDao.findByUid",fetchType = FetchType.LAZY)) })
- 一对一
@Select("select * from account") @Results(id = "accountMap",value = { @Result(id = true,column = "id",property = "id"), @Result(column = "uid",property = "uid"), @Result(column = "money",property = "money"), @Result(column = "uid",property = "user",one = @One( select = "com.ssm.dao.IUserDao.findById",fetchType= FetchType.EAGER)) })
- 一对多,
-
缓存的配置
-
一级缓存默认开启
-
二级缓存开启
- SqlMapConfig.xml
<!--配置开启二级缓存--> <settings> <setting name="cacheEnabled" value="true"/> </settings>
- IUserDao.java
//开启二级缓存 @CacheNamespace(blocking = true) public interface IUserDao {……}
-