当前位置: 代码迷 >> 综合 >> Mybatis第五讲(主键获取 缓存机制 一级缓存 二级缓存 延迟加载)
  详细解决方案

Mybatis第五讲(主键获取 缓存机制 一级缓存 二级缓存 延迟加载)

热度:43   发布时间:2023-12-15 15:40:42.0

主键获取

应用场景:用户注册成功后直接算是登录成功的状态,在个人信息或其他页面需要使用到用户的信息,那么此时就需要通过id来获取,或者注册成功后将用户信息携带过去。

总结:在添加数据后获取到当前添加的这条数据的主键ID

<insert id="insertUser" parameterType="user"><!-- 自增主键:先插入数据才有主键IDselectKey 用于在添加时查询当前语句生成的主键IDorder:指定查询主键的sql在添加语句之前还是之后去执行last_insert_id():用于获取当前添加的语句生成的主键IDkeyProperty:指定将查询到的主键值给哪个属性resultType:指定返回值的类型非自增型的通常使用的是UUID(字符串)生成使用uuid来作为主键的话,先生成主键然后再插入数据--><selectKey order="AFTER" keyProperty="uid" resultType="int">select LAST_INSERT_ID()</selectKey><!-- <selectKey order="BEFORE" keyProperty="uid" resultType="java.lang.String">select uuid()</selectKey> -->insert into t_user(uname,upwd,phone,address,hireDate)values(#{uname},#{upwd},#{phone},#{address},#{hireDate})</insert>

测试代码

@Test
public void testInsertUser() throws IOException {
    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = factory.openSession();IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);//创建User对象设置要添加的信息User user = new User();//给user对象设置一个uiduser.setUid(100);user.setUname("路长风");user.setUpwd("456");user.setAddress("万国志");user.setPhone("12345679");user.setHireDate(new Date());userMapper.insertUser(user);System.out.println(user);//增删改都需要提交事务sqlSession.commit();sqlSession.close();inputStream.close();
}

测试结果

User [uid=26, uname=路长风, upwd=456, phone=12345679, address=万国志, hireDate=Fri Apr 03 10:03:43 CST 2020, orderList=null]

缓存机制

在这里插入图片描述一级缓存
在Mybatis中一级缓存是默认开启的

同一个事务,查询uid=1的数据,先从缓存区中查找,如果没有就去数据库中查找,将数据存储到缓存区中,

当该事务再次使用uid=1的数据时,会先从缓存区中查找,如果在查找之前修改了uid=1的数据,那么会清除掉缓存区中的数据,再次从数据库中查找后放到缓存区

@Test
public void testQueryUserById2() {
    SqlSession sqlSession = factory.openSession();IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);User user1 = userMapper.queryUserById(1);System.out.println(user1);//修改动作IUserMapper userMapper3 = sqlSession.getMapper(IUserMapper.class);User user = new User();user.setUid(1);user.setUpwd("88888888");userMapper3.updateUser(user);sqlSession.commit();IUserMapper userMapper2 = sqlSession.getMapper(IUserMapper.class);User user2 = userMapper2.queryUserById(1);System.out.println(user2);sqlSession.close();
}

二级缓存
需要两个步骤:

1、配置全局参数,开启二级缓存

2、指定要给那个映射文件开启二级缓存

3、在使用另一个事务之前需要先关闭当前的事务

事务A获取uid=1的数据,先从缓存区中查看是否存在,存在直接用,不存在就去数据库获取将获取的数据存放到缓存区中;

事务B如果需要获取uid=1的数据,也是先从缓存区中查找,如果有就使用,没有就直接去数据库获取再存放到缓存区中;

此时,如果任意一个事务对uid=1的数据做了增删改的操作,那么会将缓存区中的数据清掉,那么其它的事务想要再次获取uid=1的数据,就需要去数据库中查询,再将查询到的结果存到缓存区中,以保证数据的一致性(多个事务在操作同一个数据时,拿到的结果是一致的)
在sqlMapConfig配置文件中开启二级缓存

	<settings><!-- 开启二级缓存 --><setting name="cacheEnabled" value="true"/><!-- true代表开启全局的延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- true代表所有关联属性在一开始就加载,3.4.1版本后默认值为true --><setting name="aggressiveLazyLoading" value="false"/></settings>

在要开启二级缓存的映射文件中加入cache标签

<!-- 标识该xml文件开启了二级缓存机制 --><cache></cache>
/*** 每个sqlSession就是一个事务* 如果缓存生效的话,那么对应的sql语句只执行一次*/
@Test
public void testQueryUSerById() {
    //创建事务ASqlSession sqlSession01 = factory.openSession();//事务A获取了uid=1的用户信息IUserMapper userMapper = sqlSession01.getMapper(IUserMapper.class);User user = userMapper.queryUserById(1);System.out.println(user);sqlSession01.close();//创建事务C用于修改uid=1的信息SqlSession sqlSession03 = factory.openSession();IUserMapper userMapper3 = sqlSession03.getMapper(IUserMapper.class);User user3 = new User();user3.setUid(1);user3.setUpwd("7777777");userMapper3.updateUser(user3);//提交事务sqlSession03.commit();sqlSession03.close();//创建事务BSqlSession sqlSession02 = factory.openSession();//事务B获取uid=1的信息IUserMapper userMapper2 = sqlSession02.getMapper(IUserMapper.class);User user2 = userMapper2.queryUserById(1);System.out.println(user2);sqlSession02.close();
}

区别:一级缓存是一个每个事务都有自己的缓存区,二级缓存指的是多个事务共用了同一个缓存区

延迟加载

概念:在需要的时候才执行对应的sql

例如:查询指定用户的订单信息,关联用户信息 一对一关系

首先是要显示出订单的信息,用户的信息是在使用user对象才进行查询

<settings><!-- true代表开启全局的延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- true代表所有关联属性在一开始就加载,3.4.1版本后默认值为true --><setting name="aggressiveLazyLoading" value="false"/>
</settings>
<resultMap type="order" id="queryOrderInfoResultMap"><id column="order_id" property="order_id"/><result column="order_create_time" property="order_create_time"/><result column="order_status" property="order_status"/><result column="uid" property="uid"/><!-- 延迟加载select:指定要执行的sql语句column:指定查询参数对应的列的字段名--><association property="user" javaType="user" select="cn.yunhe.dao.IUserMapper.querUserById" column="uid"><id column="uid" property="uid"/><result column="uname" property="uname"/><result column="upwd" property="upwd"/><result column="address" property="address"/><result column="phone" property="phone"/><result column="hireDate" property="hireDate"/></association>
</resultMap>
<select id="queryOrderInfo" parameterType="int" resultMap="queryOrderInfoResultMap">select * from t_orders where uid=#{uid}
</select>
  相关解决方案