一、Mybatis中的延迟加载
- 目的:不浪费内存空间
- 主要配置
- 如何进行配置
- 主配置文件中的开启步骤
- 如何进行配置
二、Mybatis中的缓存
- 缓存的基本概念
2.1 一级缓存
2.2 触发清空一级缓存的情况
2.3 二级缓存(需要逐级开启)
- 步骤1:图示
- 步骤2:图示(第二步和第三步在一起)
- 二级缓存关系图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4uBlyZfp-1624207352747)(https://note.youdao.com/yws/public/resource/45ac5bf49ce7bf36c5696e744cd381b7/xmlnote/48DD19574D9C428B95F4F6D5227FFE5B/33869)]- 注:虽然二级缓存没有发起查询,但是创建了一个新的用户对象,这样的话就不是同一个对象了
- 图中二级缓存的数据,谁来用就把数据拿过来,创建一个新的用户,将数据存进去。
- 注:虽然二级缓存没有发起查询,但是创建了一个新的用户对象,这样的话就不是同一个对象了
三、Mybatis注解开发【实际开发重点】
3.1 Mybatis注解开发的环境搭建
- 使用注意事项:
- 在Mybatis中针对CRUD一共有四个注解
@Select @Insert @Delete @Update
- 注解开发的时候,就不能在同一个dao下,再选择用xml开发
- 注解和xml方式只能用一种
- 主配置文件需要有(SqlMapConfig.xml)
- 指定带有注解的dao接口所在位置
<mappers> <package name="com.kami.dao"></package> <!-- 做区分 --> <!-- 配置xml的方式--> <mapper resource="com/kami/dao/IUserDao.xml"></package> <!-- 配置注解的方式--> <mapper class="com.kami.dao.IUserDao"></package> </mappers>
- 注解能替代xml文件的原理
3.2 Mybatis中属性和数据库表列的不对应的问题
- 用@Results和@Result注解解决对应关系
/** * 查询所有用户 * @return */ @Select("select * from user") @Results(value={ @Result(id=true,column = "id",property = "userId"), @Result(column = "username",property = "userName"), @Result(column = "address",property = "userAddress"), @Result(column = "sex",property = "userSex"), @Result(column = "birthday",property = "userBirthday") }) List<User> findAll();
- 缺点每个方法都要写(冗余代码)
- 如歌重复使用的解决方法:@Results中可以提供唯一标志【id=“userMap”】(这样其他方法也可以使用了)
- 其他方法用@ResultMap直接引用就可以了(可以引用多个)
/** * 查询所有用户 * @return */ @Select("select * from user") @Results(id="userMap",value={ @Result(id=true,column = "id",property = "userId"), @Result(column = "username",property = "userName"), @Result(column = "address",property = "userAddress"), @Result(column = "sex",property = "userSex"), @Result(column = "birthday",property = "userBirthday") }) List<User> findAll(); //其他方法引用时 /** * 根据id查询用户 * @param userId * @return */ /* //引用多个的写法 @ResultMap(value={"userMap", "accountMap"}) */ @Select("select * from user where id=#{id} ") @ResultMap("userMap") User findById(Integer userId);
3.3 Mybatis注解开发对一,对多的查询配置
- 用@Results下@Result注解中的属性(对应的注解配置)
- @One
- @more
- 两个注解的属性有
- select:查询的唯一标志(全限定类名+方法名)
- fetchType:LAZY->延迟加载,EAGER->立即加载
- 两个注解的属性有
- 注:对多时->延迟加载。对一时->立即加载。
- 一个账户只能属于一个用户的案例代码(对一)【只写了关键代码】
- 账户实体类中包含User
//多对一(mybatis中称之为一对一)的映射:一个账户只能属于一个用户 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; }
- IUserDao接口中,根据id查询用户
/** * 根据id查询用户 * @param userId * @return */ @Select("select * from user where id=#{id} ") @ResultMap("userMap") User findById(Integer userId);
- IAccountDao接口中
/** * 查询所有账户,并且获取每个账户所属的用户信息 * @return */ @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.itheima.dao.IUserDao.findById",fetchType= FetchType.EAGER)) }) List<Account> findAll();
- 一个用户对应多个账户的案例代码(对多)【只写了关键代码】
- 用户实体类中包含Accounts
//一对多关系映射:一个用户对应多个账户 private List<Account> accounts; public List<Account> getAccounts() { return accounts; } public void setAccounts(List<Account> accounts) { this.accounts = accounts; }
- IAccountsDao接口中,根据用户id查询账户信息
/** * 根据用户id查询账户信息 * @param userId * @return */ @Select("select * from account where uid = #{userId}") List<Account> findAccountByUid(Integer userId);
- IUserDao接口中
/** * 查询所有用户 * @return */ @Select("select * from user") @Results(id="userMap",value={ @Result(id=true,column = "id",property = "userId"), @Result(column = "username",property = "userName"), @Result(column = "address",property = "userAddress"), @Result(column = "sex",property = "userSex"), @Result(column = "birthday",property = "userBirthday"), @Result(property = "accounts",column = "id", many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid", fetchType = FetchType.LAZY)) }) List<User> findAll();
3.4 Mybatis注解开发,使用二级缓存
- Mybatis中一级缓存不用开启,也不用操作
- 创建两次SqlSession对象,和创建两个代理对象
- 虽然执行的方法一样,但是两个缓存是不一样的了
- 如果想做到两次用同一个缓存,就需要使用到二级缓存
- 开启后,在第二次查询时候,就不用再次发起查询。
- 开启步骤:(配置文件和dao,还有操作都要支持二级缓存)
- SqlMapConfig.xml中配置开启二级缓存
<!--配置开启二级缓存--> <settings> <setting name="cacheEnabled" value="true"/> </settings>
- IUserDao接口上加一个注解就可以解决(dao,还有操作都要支持二级缓存)
@CacheNamespace(blocking = true)
- 测试二级缓存的类
package com.itheima.test; import com.itheima.dao.IUserDao; import com.itheima.domain.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.InputStream; /** * @author Kami * @Company http://www.ithiema.com */ public class SecondLevelCatchTest { private InputStream in; private SqlSessionFactory factory; @Before public void init()throws Exception{ in = Resources.getResourceAsStream("SqlMapConfig.xml"); factory = new SqlSessionFactoryBuilder().build(in); } @After public void destroy()throws Exception{ in.close(); } @Test public void testFindOne(){ SqlSession session = factory.openSession(); IUserDao userDao = session.getMapper(IUserDao.class); User user = userDao.findById(57); System.out.println(user); session.close();//释放一级缓存 SqlSession session1 = factory.openSession();//再次打开session IUserDao userDao1 = session1.getMapper(IUserDao.class); User user1 = userDao1.findById(57); System.out.println(user1); session1.close(); } }