一、延迟加载
1、问题
假如一个用户有100个账户,那么在查询用户信息的时候要不要把100个账户的信息全部查出来?查出来如果不使用岂不是很浪费?没查不来如果要用怎么办?
所以:
在查询用户的时候,用户所有的账户信息应该是什么时候用,什么时候查询。
但是在查询账户的时候,要把账户所属用户的信息查出来。
延迟加载:
在真正使用数据时才发起查询,不用的时候不查询。(又叫按需查询、懒加载)
立即加载:
不管是否使用,只要调用方法立即发起查询;
一对多查询、多对多查询通常是延迟加载;
多对一查询、一对一查询通常是立即加载;
2、延迟加载演示代码(节选)
①在SqMapConfig.xml中添加配置:
<!-- 配置参数-->
<settings>
<!-- 开启mybatis支持延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
②配置关系映射和根据ID查询的SQL语句:
<!-- 定义封装account和user的resultMap-->
<resultMap id="accountMap" type="account">
<id property="id" column="id"/>
<result property="uid" column="uid"/>
<result property="money" column="money"/>
<!--一对一关系映射,配置封装user的内容(不同点)
属性说明:
select:查询用户的唯一标识;
column:用户根据id查询时,所需要的参数的值
-->
<association property="user" column="uid" javaType="user" select="com.zibo.mybatis_crud.dao.IUserDao.findById"/>
</resultMap>
<select id="findAccountByUid" resultType="account">
select * from account where uid = #{uid};
</select>
延迟加载思想:
如果查询的时候没有使用到用户的账户信息就不连着用户下的账户信息一起查询,如果下面的代码使用到了账户信息则一起进行查询;
二、缓存
1、什么是缓存
存在于内存中的临时数据;
2、为什幺使用缓存
减少与数据库的交互次数,提高执行效率;
3、什么样的数据能用缓存
1、经常查询的;
2、不经常改变;
3、数据的正确与否对最终结果影响不大;
4、一级缓存和二级缓存
一级缓存:
指的是Mybatis中SqlSession对象的缓存;
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供的一块区域中,该区域的结构是一个Map;
当我们再次查询同样的数据时,myabtis首先区判断sqlsesion中是否有,有的话直接返回;
当SqlSession消失,一级缓存也会消失;
清空缓存的方法:
sqlSession.clearCache();//此方法用于清空缓存
触发清空缓存的情况:
当调用sqlSession的添加、修改、删除、commit()、close()等方法的时候,就会清空一级缓存;
二级缓存:
指的是mybatis中sqlSessionFactor对象的缓存,由同一个sqlSessionFactor对象创建的sqlSession对象共享其缓存;
二级缓存的使用步骤:
第一步:让MyBatis框架支持二级缓存(在SqlMapConfig.xml中配置);
<!--开启二级缓存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置);
<!--开启二级缓存 -->
<cache>
第三步:让当前的操作支持二级缓存(在select中配置);
<!--在select中配置属性 -->
useCache="true"
注意:二级缓存中存放的数据不是对象,所以不是同一个对象;
三、注解开发
1、注解方式设置resultMap
2、注解方式实现CRUD
//查询所有
@Select("select * from user;")
List<User> findAll();
//保存一条数据
@Insert("insert into user(username,address,sex,birthday) values(#{username},#{address},#{sex},#{birthday});")
void save(User user);
//更新一条数据
@Update("update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id};")
void update(User user);
//删除一条数据
@Delete("delete from user where id = #{只有一个属性可以随便写仅作为占位符};")
void delete(Integer userId);
//根据id查询一条数据
@Select("select * from user where id = #{随便写};")
User findById(Integer userId);
3、演示补充
补充时间:2022年3月16日08点30分
package com.example.orderservicemanager.dao;
import com.example.orderservicemanager.po.OrderDetailPo;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface OrderDetailDao {
// 此处没有插入id,因为id是让数据库自动生成的
@Insert("INSERT INTO order_detail (status, address, account_id, product_id, deliveryman_id, settlement_id, reward_id, price, date)" +
"VALUES( #{status}, #{address}, #{accountId}, #{productId}, #{deliverymanId}, #{settlementId}, #{rewardId}, #{price}, #{date} )")
// id是自动生成的,自动赋值给id
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(OrderDetailPo orderDetailPo);
@Update("UPDATE order_detail SET status=#{status}, address=#{address}, account_id=#{accountId}, product_id=#{productId}, " +
"deliveryman_id=#{deliverymanId}, settlement_id=#{settlementId}, reward_id=#{rewardId}, price=#{price}, date=#{date} where id=#{id}")
void update(OrderDetailPo orderDetailPo);
// 这里注意数据库字段与Java类字段的映射写法
@Select("SELECT id, status, address, account_id accountId, product_id productId, deliveryman_id deliverymanId, settlement_id settlementId, " +
"reward_id rewardId, price, date from order_detail")
OrderDetailPo selectOrder(Integer id);
}