主键获取
应用场景:用户注册成功后直接算是登录成功的状态,在个人信息或其他页面需要使用到用户的信息,那么此时就需要通过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>