mybatis07-延迟加载、缓存、注解开发

1、Mybatis中的延迟加载

问题:在一对多中,当我们有一个用户,它有100个账户。
      在查询用户的时候,要不要把关联的账户查出来?
      在查询账户的时候,要不要把关联的用户查出来?
	
在查询用户时,用户下的账户信息应该是,什么时候使用,什么时候查询的。
在查询账户时,账户的所属用户信息应该是随着账户查询时一起查询出来。

什么是延迟加载
在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)
什么是立即加载
不管用不用,只要一调用方法,马上发起查询。

在对应的四种表关系中:一对多,多对一,一对一,多对多
	一对多,多对多:通常情况下我们都是采用延迟加载。
	多对一,一对一:通常情况下我们都是采用立即加载。

AccountDao.xml

 <!-- 定义封装account和user的resultMap -->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!-- 一对一的关系映射:配置封装user的内容
        select属性指定的内容:查询用户的唯一标识:
        column属性指定的内容:用户根据id查询时,所需要的参数的值
        -->
        <association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById"></association>
    </resultMap>

UserDao.xml

<!-- 定义User的resultMap-->
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <!-- 配置user对象中accounts集合的映射 -->
        <collection property="accounts" ofType="account" select="com.itheima.dao.IAccountDao.findAccountByUid" column="id"></collection>
    </resultMap>

Sqlconfig.xml

 <!--配置参数-->
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>

2、Mybatis中的缓存

1. 什么是缓存
	存在于内存中的临时数据。
2. 为什么使用缓存
	减少和数据库的交互次数,提高执行效率。
3. 什么样的数据能使用缓存,什么样的数据不能使用
	适用于缓存:
		经常查询并且不经常改变的。
		数据的正确与否对最终结果影响不大的。
	不适用于缓存:
		经常改变的数据
		数据的正确与否对最终结果影响很大的。
		例如:商品的库存,银行的汇率,股市的牌价。

Mybatis中的一级缓存和二级缓存
一级缓存:
它指的是Mybatis中SqlSession对象的缓存。
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。
该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中
查询是否有,有的话直接拿出来用。
当SqlSession对象消失时,mybatis的一级缓存也就消失了。
一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除, commit(), close()等方法时,就会清空一级缓存。

/**
* 测试一级缓存
*/
@Test
public void testFirstLevelCache(){
User user1 = userDao.findById(41);
System.out.println(user1);
// sqlSession.close();
//再次获取 SqlSession 对象
// sqlSession = factory.openSession();
sqlSession.clearCache();//此方法也可以清空缓存
userDao = sqlSession.getMapper(IUserDao.class);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
/**
* 测试缓存的同步
*/
@Test
public void testClearlCache(){
//1.根据 id 查询用户
User user1 = userDao.findById(41);
System.out.println(user1);
//2.更新用户信息
user1.setUsername("update user clear cache");
user1.setAddress("北京市海淀区");
userDao.updateUser(user1);
//3.再次查询 id 为 41 的用户
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
当执行sqlSession.close()后,再次获取sqlSession并查询id=41的User对象时,又重新执行了sql
语句,从数据库进行了查询操作

二级缓存:
它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
二级缓存的使用步骤:
第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)

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

第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
第三步:让当前的操作支持二级缓存(在select标签中配置)
将 UserDao.xml 映射文件中的标签中设置useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。注意: 针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。

<mapper namespace="com.itheima.dao.IUserDao">
    <cache/><!-- 开启二级缓存的支持 -->
    <!--<cache>标签表示当前这个 mapper 映射将使用二级缓存,
    区分的标准就看 mapper 的 namespace 值-->
    <select id="findById" resultType="user" parameterType="int" useCache="true">
        select * from user where id=#{id}
    </select>
</mapper>

测试二级缓存

public class SecondLevelCacheTest {
private InputStream in;
private SqlSessionFactory factory;
@Before//用于在测试方法执行之前执行
public void init()throws Exception{
	//1.读取配置文件,生成字节输入流
	in = Resources.getResourceAsStream("SqlMapConfig.xml");
	//2.获取 SqlSessionFactory
	factory = new SqlSessionFactoryBuilder().build(in);
} 
@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
	in.close();
}
/**
* 测试一级缓存
*/
@Test
public void testFirstLevelCache(){
	SqlSession sqlSession1 = factory.openSession();
	IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
	User user1 = dao1.findById(41);
	System.out.println(user1);
	sqlSession1.close();//一级缓存消失
	SqlSession sqlSession2 = factory.openSession();
	IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
	User user2 = dao2.findById(41);
	System.out.println(user2);
	sqlSession2.close();
	System.out.println(user1 == user2);
	}
}

经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。
tips: 当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化方式来保存对象。
二级缓存存放的是数据,不是对象,虽然没有发起查询,但是却新建了用户对象,所以最后输出的都是false。
在这里插入图片描述

3、Mybatis中的注解开发

常用注解

@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用

环境搭建

单表CRUD操作(代理Dao方式)

多表查询操作

缓存的配置

发布了11 篇原创文章 · 获赞 1 · 访问量 185

猜你喜欢

转载自blog.csdn.net/weixin_45330007/article/details/104464263