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

主键获取

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

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

<insert id="insertUser" parameterType="user">
    <!-- 
   自增主键:先插入数据才有主键ID
   selectKey 用于在添加时查询当前语句生成的主键ID
   order:指定查询主键的sql在添加语句之前还是之后去执行
   last_insert_id():用于获取当前添加的语句生成的主键ID
   keyProperty:指定将查询到的主键值给哪个属性
   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对象设置一个uid
    user.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() {
    //创建事务A
    SqlSession 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();

    //创建事务B
    SqlSession 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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值