文章目录
- 加载时机(检索策略)
- 延迟加载
- 立即加载
- Mybatis 实现延迟加载
- Mybatis中的一级缓存和二级缓存
- Mybatis的注解开发
- 环境搭建
- 单表CRUD操作
- 建立实体类属性与数据库表列的对应关系
- 多表查询操作
- 缓存的配置
加载时机(检索策略)
- 当一个用户下有非常多的账户时,我们查询一个用户后,其实体类中账户集合会非常的大,那么在查询的时候,应该是什么时候用到其账户信息,什么时候获取
- 当我们在查询账户的时候,需要一同得到其账户所属的用户信息,那么在查询账户时,账户的所属用户信息应该是随着账户查询时一起查询出来
延迟加载
- 在真正使用数据时才发起查询,不用的时候不查,按需加载,也叫懒加载
- 适用范围:一对多,多对多
立即加载
- 不管用不用,只要一调用方法,就立刻发起查询
- 适用范围:多对一,一对一
Mybatis 实现延迟加载
- 实现思想:都是在用的时候才通过对方的根据id查询的配置来实现
- 使用 Assocation 实现延迟加载
<!-- select 属性指定的内容:查询用户的唯一标识: -->
<!-- column 属性指定的内容:用户根据id查询时所需要的参数的值 -->
<association property="user" column="uid" javaType="user" select="com.learn.dao.IUserDao.selectById"></association>
(1)当以上的设置配置好了过后还不能实现延迟加载,还要在主配置文件中添加设置,查看官网关于setting的介绍
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
- 使用 Collection 实现延迟加载
(1)先实现通过用户id查询账户列表这个配置,再实现以下配置,最后将主配置文件的setting配置好即可实现延迟加载
<collection property="accounts" ofType="account" select="com.learn.dao.IAccountDao.findAccountByUId"></collection>
Mybatis中的一级缓存和二级缓存
- 缓存:即存在于内存的临时数据
- 使用缓存:可减少和数据库的交互次数,提高执行效率
- 适用于缓存:经常查询并且不经常改变的;数据的正确与否对结果影响不大的。避免缓存中的数据与数据库中的不一致导致异常。
- 不适用缓存:数据的正确与否对结果影响很大(商品的库存,银行的汇款,股市的牌价等)
- Mybatis 中的一级缓存:指的是Mybatis中SqlSession对象的缓存
❤ 当我们执行查询之后,查询结果会同时存入到SqlSession
为我们提供的一块区域中,该区域是一个Map,当我们再次查询的时候,会先在SqlSwssion
对象中查询是否有,有就直接读取使用;
❤ 当SqlSession对象关闭时,mybatis的一级缓存就清空了,因此可以通过关闭再开启SqlSession的方法来清空一级缓存
❤ 当调用SqlSession的修改、添加、删除、提交、关闭、clearCache()
等方法时就会清空一级缓存,因此可通过这些操作来同步刷新一级缓存 - Mybatis 中的二级缓存:指的是Mybatis中
SqlSessionFactory
对象的缓存,由同一个SqlSessionFactory
对象创建的SqlSession
共享其缓存
❤ 使用步骤:
(1)让Mybatis支持二级缓存 ---- 在SqlMapConfig.xml
中配置
(2)让当前的映射文件支持二级缓存 ---- 在IUserDao.xml
中配置
(3)让当前的操作中支持二级缓存 ---- 在<select>
标签中配置
❤ 代码实现:
SqlMapConfig.xml
<settings>
<setting name="cacheEnable" value="true"/>
</settings>
IUserDao.xml
<!-- 开启user支持二级缓存 -->
<cache/>
<!-- select标签中开启 -->
<select id="findAll" resultType="user" useCache="true">
select * from user
</select>
Mybatis的注解开发
环境搭建
- 注解开发只是代替了映射配置文件,主配置文件还是需要的
- 先创建工程,导入依赖,再创建实体类和Dao接口以及主配置文件
- 只要使用了注解开发,同时也有配置文件,不管用不用到这个配置文件,都会报错;因此要不将映射配置文件删除,要不换到别的地方,才可以继续。也就意味着:不能在同一个Dao中采用两种方式开发,只能二选一
单表CRUD操作
- Mybatis中针对CRUD一共有4个注释:
@SELECT @INSERT @UPDATE @DELETE
- 注解中的括号中写入SQL语句即可当注解中的value只有一个时可以直接写value,否则需要写
(value={"..."})
,即标准格式为@Select(value={"select * from user"})
- 使用方法:
@Select("select * from user")
List<User> findAll();
@Insert("insert into user(userName,age) values(#{userName},#{age})")
void saveUser(User user);
@Update("update user set userName=#{userName},age=#{age} where id=#{id}")
void updateUser(User user);
@Delete("delete from user where id=#{id}")
void deleteUser(Integer id);
@Select("select * from user where id=#{id}")
User selectUserById(Integer id);
@Select("select * from user where userName like #{userName} ")
User selectUserLikeName(String userName);
@Select("select count(*) from user")
int findTotal();
建立实体类属性与数据库表列的对应关系
- 当实体类属性名与数据库列名不一致的时候,Mybatis就无法完成自动的对应关系映射那么查询结果就不能实现自动封装
- 最简单的方法是在sql语句中配置别名,传统方法是在映射配置文件中配置,注解也可以配置别名
- 当配置好一个过后,可以指定一个id,这样后面的方法就可以通过这个 id 查找到这个配置
@Select("select * from user")
@Results(id="userMap", value={
@Result(id=true, column="id", property="userId"),
@Result(column="name", property="userName",
@Result(column="age", property="userAge"
})
List<User> findAll();
@Select("select * from user where id=#{id}")
@ResultMap("userMap")
User selectUserById(Integer id);
多表查询操作
- 实现步骤
(1)建立数据库表并配置表间联系
(2)建立实体类并表示出实体类之间的联系
(3)配置封装结果映射
(4)FetchType
的属性即为检索策略,对应立即加载和延时加载 - 多对一 (Mybatis中也称之为一对一)
//一个账户只能属于一个用户
@Select("select * from account")
@Results(id="accountMap", value={
@Result(id=true, column="id", property="id"),
@Result(column="uid", property="uid",
@Result(column="money", property="money",
@Result(property="user", column="uid", one=@One(select="com.learn.dao.IUserDao.selectById", fetchType=FetchType.EAGER))
})
List<User> findAccountAndUser();
- 一对多
@Select("select * from user")
@Results(id="userMap", value={
@Result(id=true, column="id", property="userId"),
@Result(column="name", property="userName",
@Result(column="age", property="userAge"
@Result(property="accounts", column="id", many=@Many(select="com.learn.dao.IAccountDao.selectAccountByUId", fetchType=FetchType.LAZY))
})
List<User> findAll();
缓存的配置
- 一级缓存是自动开启的,无需手动开启
- 二级缓存的需要配置
(1)先在主配置文件配置,但是现在的版本默认是开启的
(2)在Dao接口类中配置
//开启二级缓存
@CacheNameSpace(blocking=true)
public interface IUserDao{
...
}