typora-copy-images-to: img

typora-copy-images-to: img

MyBatis_02

学习目标

  • 掌握Mybatis一对一关系(重点)
  • 掌握Mybatis一对多关系(重点)
  • 掌握Mybatis多对多关系(重点)
  • 掌握Mybatis的延迟加载(掌握)
  • 掌握Mybatis一级缓存(了解)
  • 掌握Mybatis二级缓存(掌握)
  • 掌握Mybatis注解开发(掌握)

第一章-MyBatis缓存(了解)

知识点-缓存概述

1.目标

  • 掌握MyBatis缓存类别

2.路径

  1. 缓存概述
  2. 为什么使用缓存
  3. 缓存的适用情况
  4. MyBatis缓存类别

3.讲解

3.1缓存概述

  1. 缓存就是一块内存空间.保存临时数据

3.2为什么使用缓存

  1. 将数据源(数据库或者文件)中的数据读取出来存放到缓存中,再次获取的时候 ,直接从缓存中获取,可以减少和数据库交互的次数,这样可以提升程序的性能!

3.3缓存的适用情况

  • 适用于缓存的:经常查询但不经常修改的(eg: 省市,类别数据),数据的正确与否对最终结果影响不大的
  • 不适用缓存的:经常改变的数据 , 敏感数据(例如:股市的牌价,银行的汇率,银行卡里面的钱)等等,

3.4 MyBatis缓存类别

  1. 一级缓存:它是sqlSession对象的缓存,自带的(不需要配置)不可卸载的(不想使用还不行). 一级缓存的生命周期与sqlSession一致。
  2. 二级缓存:它是SqlSessionFactory的缓存。只要是同一个SqlSessionFactory创建的SqlSession就共享二级缓存的内容,并且可以操作二级缓存。二级缓存如果要使用的话,需要我们自己手动开启(需要配置的)。

4.小结

  1. 缓存: 内存空间, 保存临时数据
  2. 为什么要使用缓存? 提高性能
  3. 适合使用缓存? 经常查询的, 不经常改变
  4. MyBatis的缓存类别

    • 一级缓存
    • 二级缓存

知识点-一级缓存

1.目标

  • 掌握MyBatis一级缓存

2.路径

  1. 证明一级缓存的存在
  2. 一级缓存分析
  3. 测试一级缓存清空

3.讲解

3.1证明一级缓存的存在

  1. @Test
  2. public void testFindAll(){
  3. //1. 获取sqlSession对象
  4. SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
  5. //2. 通过sqlSession对象获取UserDao接口的代理对象
  6. UserDao userDao = sqlSession.getMapper(UserDao.class);
  7. //3. 调用UserDao接口的代理对象的findAll方法获取所有联系人的信息
  8. List<User> userList = userDao.findAll();
  9. for (User user : userList) {
  10. System.out.println(user);
  11. }
  12. System.out.println("分割线----------------------------------");
  13. UserDao userDao2 = sqlSession.getMapper(UserDao.class);
  14. List<User> userList2 = userDao2.findAll();
  15. for (User user : userList2) {
  16. System.out.println(user);
  17. }
  18. //4. 提交事务关闭资源
  19. SqlSessionFactoryUtils.commitAndClose(sqlSession);
  20. }

3.2一级缓存分析

  1. ![](https://gitee.com/tgl_bug/typora-table/raw/master/img/20210121133544.png#alt=img)
  2. 第一次发起查询用户 id 1 的用户信息,先去找缓存中是否有 id 1 的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。第二次发起查询用户 id 1 的用户信息,先去找缓存中是否有 id 1 的用户信息,缓存中有,直接从缓存中获取用户信息。
  3. 如果 sqlSession 去执行 commit操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

3.3测试一级缓存清空

  • 调用sqlSession的commit()或者clearCache()或者close()都能清除一级缓存
  1. @Test
  2. public void testFindAll(){
  3. //1. 获取sqlSession对象
  4. SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
  5. //2. 通过sqlSession对象获取UserDao接口的代理对象
  6. UserDao userDao = sqlSession.getMapper(UserDao.class);
  7. //3. 调用UserDao接口的代理对象的findAll方法获取所有联系人的信息
  8. List<User> userList = userDao.findAll();
  9. for (User user : userList) {
  10. System.out.println(user);
  11. }
  12. System.out.println("分割线----------------------------------");
  13. //清除一级缓存: 1. sqlSession.close() 2. sqlSession.commit() 3. sqlSession.clearCache() 4. 数据发生增删改
  14. sqlSession.clearCache()
  15. UserDao userDao2 = sqlSession.getMapper(UserDao.class);
  16. List<User> userList2 = userDao2.findAll();
  17. for (User user : userList2) {
  18. System.out.println(user);
  19. }
  20. //4. 提交事务关闭资源
  21. SqlSessionFactoryUtils.commitAndClose(sqlSession);
  22. }
  • 更新数据也会清空一级缓存
  1. @Test
  2. public void testFindAll(){
  3. //1. 获取sqlSession对象
  4. SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
  5. //2. 通过sqlSession对象获取UserDao接口的代理对象
  6. UserDao userDao = sqlSession.getMapper(UserDao.class);
  7. //3. 调用UserDao接口的代理对象的findAll方法获取所有联系人的信息
  8. List<User> userList = userDao.findAll();
  9. for (User user : userList) {
  10. System.out.println(user);
  11. }
  12. System.out.println("分割线----------------------------------");
  13. //清除一级缓存: 1. sqlSession.close() 2. sqlSession.commit() 3. sqlSession.clearCache() 4. 数据发生增删改
  14. userDao.deleteById(9);
  15. UserDao userDao2 = sqlSession.getMapper(UserDao.class);
  16. List<User> userList2 = userDao2.findAll();
  17. for (User user : userList2) {
  18. System.out.println(user);
  19. }
  20. //4. 提交事务关闭资源
  21. SqlSessionFactoryUtils.commitAndClose(sqlSession);
  22. }

4.小结

  1. 一级缓存: 依赖sqlSession对象的, 自带的不可卸载的. 一级缓存的生命周期和sqlSession一致
  2. 一级缓存清空

    • sqlSession销毁
    • 增删改 提交之后

知识点-二级缓存

1.目标

  • 掌握MyBatis二级缓存

2.路径

  1. 二级缓存的结构
  2. 二级缓存的使用
  3. 二级缓存的测试

3.讲解

  1. 二级缓存是SqlSessionFactory的缓存。只要是同一个SqlSessionFactory创建的SqlSession就共享二级缓存的内容,并且可以操作二级缓存.

3.1二级缓存的结构

MyBatis_02 - 图1

3.2二级缓存的使用

  • 在 SqlMapConfig.xml 文件开启二级缓存
    1. <!--配置开启二级缓存-->
    2. <settings>
    3. <setting name="cacheEnabled" value="true"/>
    4. </settings>
  1. **因为 cacheEnabled 的取值默认就为 true**,所以这一步可以省略不配置。为 true 代表开启二级缓存;为 false 代表不开启二级缓存。
  • 配置相关的 Mapper 映射文件
    <cache> 标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。

    1. <?xml version="1.0" encoding="UTF-8" ?>
    2. <!DOCTYPE mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.itheima.dao.UserDao">
    6. <!--配置二级缓存-->
    7. <cache/>
    8. <select id="findAll" resultType="user">
    9. select * from t_user
    10. </select>
    11. <delete id="deleteById" parameterType="int">
    12. delete from t_user where uid=#{id}
    13. </delete>
    14. </mapper>
  • 要进行二级缓存的POJO类必须实现Serializable接口

3.3测试

  1. @Test
  2. public void test02(){
  3. //二级缓存
  4. //1. 获取sqlSession对象
  5. SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
  6. //2. 通过sqlSession对象获取UserDao接口的代理对象
  7. UserDao userDao = sqlSession.getMapper(UserDao.class);
  8. //3. 调用UserDao接口的代理对象的findAll方法获取所有联系人的信息
  9. List<User> userList = userDao.findAll();
  10. for (User user : userList) {
  11. System.out.println(user);
  12. }
  13. SqlSessionFactoryUtils.commitAndClose(sqlSession);
  14. System.out.println("分割线----------------------------------");
  15. //第二次查询,使用不同的SqlSession对象,但是使用同一个SqlSessionFactory对象
  16. SqlSession sqlSession2 = SqlSessionFactoryUtils.openSession();
  17. UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
  18. //数据发生增删改
  19. userDao2.deleteById(8);
  20. List<User> userList2 = userDao2.findAll();
  21. for (User user : userList2) {
  22. System.out.println(user);
  23. }
  24. SqlSessionFactoryUtils.commitAndClose(sqlSession2);
  25. }
  1. 经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。

4.小结

4.1注意事项

  1. 当我们在使用二级缓存时,缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化 方式来保存对象。

MyBatis_02 - 图2

第二章 - Mybatis 的多表关联查询【重点】

知识点-一(多)对一

1.需求

  1. 本次案例以简单的用户和账户的模型来分析 Mybatis 多表关系。用户为 User 表,账户为Account 表。一个用户(User)可以有多个账户(Account),但是一个账户(Account)只能属于一个用户(User)。具体关系如下:

MyBatis_02 - 图3

  1. **查询所有账户信息, 关联查询账户的用户名和地址**。
  2. 因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。
  • 数据库的准备
  1. CREATE TABLE t_account(
  2. aid INT PRIMARY KEY auto_increment,
  3. money DOUBLE,
  4. uid INT
  5. );
  6. ALTER TABLE t_account ADD FOREIGN KEY(uid) REFERENCES t_user(uid);
  7. INSERT INTO `t_account` VALUES (null, '1000', '1');
  8. INSERT INTO `t_account` VALUES (null, '2000', '1');
  9. INSERT INTO `t_account` VALUES (null, '1000', '2');
  10. INSERT INTO `t_account` VALUES (null, '2000', '2');
  11. INSERT INTO `t_account` VALUES (null, '800', '3');

2.分析

  • 查询语句
  1. select * from t_user u,t_account a where a.uid=u.uid and u.uid=#{uid}

3.实现

  • 修改Account.java
    在 Account 类中加入 User类的对象作为 Account 类的一个属性。
  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class Account implements Serializable {
  5. private Integer aid;
  6. private Double money;
  7. private Integer uid;
  8. /**
  9. * 表示Account和User的一对一关系
  10. */
  11. private User user;
  12. }
  • AccountDao.java
  1. /**
  2. * 包名:com.itheima.dao
  3. *
  4. * @author Leevi
  5. * 日期2020-07-30 10:03
  6. */
  7. public interface AccountDao {
  8. /**
  9. * 根据账户的aid查询出账户信息,并且连接t_user表获取该账户的用户信息
  10. * @param aid
  11. * @return
  12. */
  13. Account findAccountUserByAid(int aid);
  14. }
  • AccountDao.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.itheima.dao.AccountDao">
  6. <!--
  7. 使用resultMap标签自定义映射规则
  8. -->
  9. <resultMap id="accountUserMap" type="Account">
  10. <id column="aid" property="aid"></id>
  11. <result column="money" property="money"></result>
  12. <result column="uid" property="uid"></result>
  13. <!--
  14. 要进行一对一的映射配置
  15. property表示要映射的pojo的属性名
  16. javaType表示要进行映射的POJO的属性的类型
  17. -->
  18. <association property="user" javaType="User">
  19. <result column="uid" property="uid"></result>
  20. <result column="username" property="username"></result>
  21. <result column="sex" property="sex"></result>
  22. <result column="birthday" property="birthday"></result>
  23. <result column="address" property="address"></result>
  24. </association>
  25. </resultMap>
  26. <select id="findAccountUserByAid" parameterType="int" resultMap="accountUserMap">
  27. select * from t_account a,t_user u where a.uid=u.uid and a.aid=#{aid}
  28. </select>
  29. </mapper>

4.小结

知识点-一对多

1.需求

  1. 查询所有用户信息及用户关联的账户信息。

2.分析

  1. 分析: 用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,我们想到了左外连接查询比较合适。
  • sql语句
  1. select * from t_user u,t_account a where a.uid=u.uid and u.uid=#{uid}

3.实现

  • Account.java
  1. public class Account {
  2. private Integer aid;
  3. private Integer uid;
  4. private Double money;
  5. }
  • User.java
    为了能够让查询的 User 信息中,带有他的个人多个账户信息,我们就需要在 User 类中添加一个集合,
    用于存放他的多个账户信息,这样他们之间的关联关系就保存了。
  1. public class User implements Serializable{
  2. private int uid;
  3. private String username;// 用户姓名
  4. private String sex;// 性别
  5. private Date birthday;// 生日
  6. private String address;// 地址
  7. //表达关系:1个用户对应多个账户
  8. private List<Account> accountList;
  9. }
  • UserDao.java
  1. /**
  2. * 包名:com.itheima.dao
  3. *
  4. * @author Leevi
  5. * 日期2020-07-30 08:41
  6. */
  7. public interface UserDao {
  8. User findUserAccountByUid(int uid);
  9. }
  • UserDao.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.itheima.dao.UserDao">
  6. <!--
  7. 使用resultMap标签,自定义映射规则
  8. -->
  9. <resultMap id="userAccountMap" type="User">
  10. <id column="uid" property="uid"></id>
  11. <result column="address" property="address"></result>
  12. <result column="username" property="username"></result>
  13. <result column="sex" property="sex"></result>
  14. <result column="birthday" property="birthday"></result>
  15. <!--
  16. 使用collection标签进行一对多映射
  17. -->
  18. <collection property="accountList" ofType="Account">
  19. <result column="aid" property="aid"></result>
  20. <result column="money" property="money"></result>
  21. <result column="uid" property="uid"></result>
  22. </collection>
  23. </resultMap>
  24. <select id="findUserAccountByUid" parameterType="int" resultMap="userAccountMap">
  25. select * from t_user u,t_account a where a.uid=u.uid and u.uid=#{uid}
  26. </select>
  27. </mapper>

4.小结

知识点-多对多

1. 需求

  1. 通过前面的学习,我们使用 Mybatis 实现一对多关系的维护。多对多关系其实我们看成是双向的一对多关系。用户与角色的关系模型就是典型的多对多关系.

MyBatis_02 - 图4

  1. 需求:实现查询所有角色对象并且加载它所分配的用户信息。
  • 建表语句
  1. CREATE TABLE t_role(
  2. rid INT PRIMARY KEY AUTO_INCREMENT,
  3. rName varchar(40),
  4. rDesc varchar(40)
  5. );
  6. INSERT INTO `t_role` VALUES (null, '校长', '负责学校管理工作');
  7. INSERT INTO `t_role` VALUES (null, '副校长', '协助校长负责学校管理');
  8. INSERT INTO `t_role` VALUES (null, '班主任', '负责班级管理工作');
  9. INSERT INTO `t_role` VALUES (null, '教务处主任', '负责教学管理');
  10. INSERT INTO `t_role` VALUES (null, '班主任组长', '负责班主任小组管理');
  11. -- 中间表(关联表)
  12. CREATE TABLE user_role(
  13. uid INT,
  14. rid INT
  15. );
  16. ALTER TABLE user_role ADD FOREIGN KEY(uid) REFERENCES t_user(uid);
  17. ALTER TABLE user_role ADD FOREIGN KEY(rid) REFERENCES t_role(rid);
  18. INSERT INTO `user_role` VALUES ('1', '1');
  19. INSERT INTO `user_role` VALUES ('3', '3');
  20. INSERT INTO `user_role` VALUES ('2', '3');
  21. INSERT INTO `user_role` VALUES ('2', '5');
  22. INSERT INTO `user_role` VALUES ('3', '4');

2.分析

  1. 查询角色我们需要用到 Role 表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE 表)才能关联到用户信息。<br />

下面是实现的 SQL 语句:

  1. select * from t_user u,user_role ur,t_role r where ur.uid=u.uid and ur.rid=r.rid and u.uid=#{uid}

3.实现

  • User.java
  1. package com.itheima.pojo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import java.io.Serializable;
  6. import java.util.Date;
  7. import java.util.List;
  8. /**
  9. * 包名:com.itheima.pojo
  10. *
  11. * @author Leevi
  12. * 日期2020-07-29 09:03
  13. */
  14. @Data
  15. @AllArgsConstructor
  16. @NoArgsConstructor
  17. public class User implements Serializable {
  18. private Integer uid;
  19. private String username;
  20. private String sex;
  21. private Date birthday;
  22. private String address;
  23. /**
  24. * user和role的一对多关系
  25. */
  26. private List<Role> roleList;
  27. }
  • Role.java
  1. public class Role {
  2. private Integer rid;
  3. private String rName;
  4. private String rDesc;
  5. }
  • UserDao.java
  1. package com.itheima.dao;
  2. import com.itheima.pojo.User;
  3. /**
  4. * 包名:com.itheima.dao
  5. *
  6. * @author Leevi
  7. * 日期2020-07-30 08:41
  8. */
  9. public interface UserDao {
  10. User findUserRoleByUid(int uid);
  11. }
  • UserDao.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.itheima.dao.UserDao">
  6. <!--使用resultMap标签,自定义连接user和role的结果集和User的映射-->
  7. <resultMap id="userRoleMap" type="User">
  8. <!--能够一一对应的属性,我不写-->
  9. <id column="uid" property="uid"></id>
  10. <result column="address" property="address"></result>
  11. <result column="username" property="username"></result>
  12. <result column="sex" property="sex"></result>
  13. <result column="birthday" property="birthday"></result>
  14. <collection property="roleList" ofType="Role">
  15. <result property="rid" column="rid"></result>
  16. <result property="rName" column="rName"></result>
  17. <result property="rDesc" column="rDesc"></result>
  18. </collection>
  19. </resultMap>
  20. <select id="findUserRoleByUid" parameterType="int" resultMap="userRoleMap">
  21. select * from t_user u,user_role ur,t_role r where ur.uid=u.uid and ur.rid=r.rid and u.uid=#{uid}
  22. </select>
  23. </mapper>

4.小结

  1. 以哪张表作为主体查询,那么就将查询到的结果封装到哪张表对应的POJO对象中
  2. 如果表的关系是一对一,那么就在一个POJO中添加另外一个POJO的对象属性
  3. 如果表的关系是一对多,那么就在一个POJO中添加另外一个POJO的集合属性
  4. 使用association标签可以进行一对一的映射
  5. 使用collection标签可以进行一对多的映射

第三章-Mybatis 延迟加载策略(重点)

知识点-Mybatis 延迟加载策略

1.目标

  1. 通过前面的学习,我们已经掌握了 Mybatis 中一对一,一对多,多对多关系的配置及实现,可以实现对象的关联查询。实际开发过程中很多时候我们并不需要总是在加载一方信息时就一定要加载另外一方的信息。 此时就是我们所说的延迟加载。
  2. 等用到另外一方(和当前关联的那一份)的数据的时候, 再去查询;
  3. 如果用不到, 不查询.

2.路径

  1. 什么是延迟加载
  2. 使用 Assocation 实现延迟加载 (多对一,一对一)
  3. Collection 实现延迟加载 (一对多)

3.讲解

3.1什么是延迟加载

  1. 延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
  2. 坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
  3. 好处: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快.

3.2使用 Assocation 实现延迟加载 (多对一,一对一)

3.2.1需求
  1. 查询账户(Account)信息并且关联查询用户(User)信息。
  2. 先查询账户(Account)信息,当我们需要用到用户(User)信息时再查询用户(User)信息。
  1. -- 1. 查询账户
  2. select * from t_account where aid=#{aid}
  3. -- 2, 再查询用户
  4. -- 再根据查询结果里面的uid查询当前账户所属的用户
  5. SELECT * FROM t_user WHERE uid = #{uid}

3.2.2实现
  • User.java
  1. public class User{
  2. private int uid;
  3. private String username;// 用户姓名
  4. private String sex;// 性别
  5. private Date birthday;// 生日
  6. private String address;// 地址
  7. }
  • Account.java
  1. public class Account {
  2. private Integer aid;
  3. private Integer uid;
  4. private Double money;
  5. //表达关系:1个用户对应1个账户
  6. private User user;
  7. }
  • AccountDao.java
  1. package com.itheima.dao;
  2. import com.itheima.pojo.Account;
  3. import java.util.List;
  4. /**
  5. * 包名:com.itheima.dao
  6. *
  7. * @author Leevi
  8. * 日期2020-07-30 10:03
  9. */
  10. public interface AccountDao {
  11. Account findAccountByAid(int aid);
  12. }
  • AccountDao.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.itheima.dao.AccountDao">
  6. <!--
  7. 编写自定义映射规则
  8. -->
  9. <resultMap id="accountUserMap" type="Account">
  10. <id column="aid" property="aid"></id>
  11. <result column="money" property="money"></result>
  12. <result column="uid" property="uid"></result>
  13. <!--
  14. 一对一映射
  15. select属性表示调用其它的select标签
  16. column属性表示往要调用的其它的select标签中传入参数
  17. fetchType="lazy"表示延迟加载(局部配置,只有配置了这个的地方才会延迟加载)
  18. -->
  19. <association property="user" javaType="User" column="uid" select="com.itheima.dao.UserDao.findUserByUid"></association>
  20. </resultMap>
  21. <select id="findAccountByAid" parameterType="int" resultMap="accountUserMap">
  22. select * from t_account where aid=#{aid}
  23. </select>
  24. </mapper>
  • UserDao.java
  1. package com.itheima.dao;
  2. import com.itheima.pojo.User;
  3. /**
  4. * 包名:com.itheima.dao
  5. *
  6. * @author Leevi
  7. * 日期2020-07-30 08:41
  8. */
  9. public interface UserDao {
  10. /**
  11. * 为了演示分步查询的一对多另写的一个方法
  12. * @param uid
  13. * @return
  14. */
  15. User findById(int uid);
  16. }
  • UserDao.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.itheima.dao.UserDao">
  6. <select id="findUserByUid" parameterType="int" resultType="User">
  7. select * from t_user where uid=#{uid}
  8. </select>
  9. </mapper>
  • 测试
  1. @Test
  2. public void test01(){
  3. SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
  4. //1. 创建AccountDao的代理对象
  5. AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
  6. // 根据aid查询帐户信息
  7. Account account = accountDao.findAccountByAid(2);
  8. System.out.println(account.getMoney());
  9. SqlSessionFactoryUtils.commitAndClose(sqlSession);
  10. }

3.3Collection 实现延迟加载 (一对多,多对多)

3.3.1需求
  1. 完成加载用户对象时,查询该用户所拥有的账户信息。
  2. 等账户信息使用的时候再查询.
  1. -- 1. 根据uid查询用户
  2. SELECT * FROM t_user where uid=#{uid}
  3. -- 2. 查询当前用户下的账户信息
  4. -- 把用户里面的uid作为条件查询账户表
  5. SELECT * FROM t_account WHERE uid = #{uid}

3.3.2实现
  • Account.java
  1. public class Account {
  2. private Integer aid;
  3. private Integer uid;
  4. private Double money;
  5. }
  • User.java
  1. public class User implements Serializable{
  2. private int uid;
  3. private String username;// 用户姓名
  4. private String sex;// 性别
  5. private Date birthday;// 生日
  6. private String address;// 地址
  7. //表达关系:1个用户对应多个账户
  8. private List<Account> accounts;
  9. }
  • UserDao.java
  1. package com.itheima.dao;
  2. import com.itheima.pojo.User;
  3. /**
  4. * 包名:com.itheima.dao
  5. *
  6. * @author Leevi
  7. * 日期2020-07-30 08:41
  8. */
  9. public interface UserDao {
  10. /**
  11. * 为了演示分步查询的一对多另写的一个方法
  12. * @param uid
  13. * @return
  14. */
  15. User findById(int uid);
  16. }
  • UserDao.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.itheima.dao.UserDao">
  6. <resultMap id="userAccountMap" type="User">
  7. <id column="uid" property="uid"></id>
  8. <result column="username" property="username"></result>
  9. <result column="sex" property="sex"></result>
  10. <result column="birthday" property="birthday"></result>
  11. <result column="address" property="address"></result>
  12. <!--进行一对多的映射-->
  13. <collection property="accountList" ofType="Account" column="uid" select="com.itheima.dao.AccountDao.findAccountListByUid"></collection>
  14. </resultMap>
  15. <select id="findById" parameterType="int" resultMap="userAccountMap">
  16. select * from t_user where uid=#{uid}
  17. </select>
  18. </mapper>
  • AccountDao.java
  1. package com.itheima.dao;
  2. import com.itheima.pojo.Account;
  3. import java.util.List;
  4. /**
  5. * 包名:com.itheima.dao
  6. *
  7. * @author Leevi
  8. * 日期2020-07-30 10:03
  9. */
  10. public interface AccountDao {
  11. /**
  12. * 根据uid查询Account的集合
  13. * @param uid
  14. * @return
  15. */
  16. List<Account> findAccountListByUid(int uid);
  17. }
  • AccountDao.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.itheima.dao.AccountDao">
  6. <select id="findAccountListByUid" parameterType="int" resultType="Account">
  7. select * from t_account where uid=#{uid}
  8. </select>
  9. </mapper>
  • 测试方法
  1. @Test
  2. public void test02(){
  3. SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
  4. UserDao userDao = sqlSession.getMapper(UserDao.class);
  5. User user = userDao.findById(1);
  6. System.out.println(user.getUsername());
  7. SqlSessionFactoryUtils.commitAndClose(sqlSession);
  8. }

4 总结

类别 特点
立即加载 只要一调用方法,则马上发起查询
延迟加载 只有在真正使用时,才发起查询,如果不用,则不查询。

第四章-MyBatis注解开发(了解)

  1. 这几年来注解开发越来越流行, Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper映射文件了。 本次我们先围绕一些基本的 CRUD来学习,再学习复杂映射关系及延迟加载。

知识点-使用 Mybatis 注解实现基本CRUD

1.目标

  • 使用 Mybatis 注解实现基本CRUD

2.路径

  1. @Insert:实现新增
  2. @Update:实现更新
  3. @Delete:实现删除
  4. @Select:实现查询
  5. @SelectKey:保存之后 获得保存的id

3.实现

  • Dao
  1. package com.itheima.dao;
  2. import com.itheima.pojo.User;
  3. import org.apache.ibatis.annotations.*;
  4. import java.util.List;
  5. /**
  6. * 包名:com.itheima.dao
  7. *
  8. * @author Leevi
  9. * 日期2020-07-30 08:41
  10. * 使用注解实现t_user表的增删改查
  11. * Select注解
  12. * Insert注解
  13. * Delete注解
  14. * Update注解
  15. * SelectKey注解
  16. */
  17. public interface UserDao {
  18. @Select("select * from t_user")
  19. List<User> findAll();
  20. @Select("select * from t_user where uid=#{id}")
  21. User findByUid(int id);
  22. @Insert("insert into t_user values (null,#{username},#{sex},#{birthday},#{address})")
  23. @SelectKey(keyProperty = "uid",keyColumn = "uid",before = false,statement="select last_insert_id()", resultType = int.class)
  24. int add(User user);
  25. @Delete("delete from t_user where uid=#{id}")
  26. int deleteById(int id);
  27. @Update("update t_user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where uid=#{uid}")
  28. int update(User user);
  29. }
  • 核心配置文件SqlMapConfig.xml

MyBatis_02 - 图5

4.小结

  1. 查询
  1. @Select("sql语句")
  1. 新增
  1. @SelectKey(keyProperty = "主键属性名",resultType = 主键Java类型,before = false,statement = "SELECT LAST_INSERT_ID()")
  2. @Insert("sql语句")
  1. 更新
  1. @Update("sql语句")
  1. 删除
  1. @Delete("sql语句)

知识点-使用Mybatis注解实现复杂关系映射开发

1.目标

  • 掌握Mybatis注解开发

2.路径

  1. 复杂关系映射的注解说明
  2. 使用注解实现一对一复杂关系映射及延迟加载
  3. 使用注解实现一对多复杂关系映射及延迟加载

3.讲解

  1. 实现复杂关系映射之前我们可以在映射文件中通过配置来实现, [@ResultMap ](/ResultMap ) 这个注解不是封装用的。
  2. 下面我们一起来学习[@Results ](/Results ) 注解, [@Result ](/Result ) 注解, [@One ](/One ) 注解, @Many注解。

3.1复杂关系映射的注解说明

  1. //该注解中可以使用单个@Result 注解,也可以使用@Result 集合
  2. @Results({@Result(), @Result() })或@Results@Result())
  • @Resutl 注解 ,代替了 标签和标签 ,
  1. @Result(column="列名",property="属性名",one=@One(select="指定用来多表查询的 sqlmapper"),many=@Many(select=""))
  2. @Resutl 注解属性说明
  3. column 数据库的列名
  4. Property 需要装配的属性名
  5. one 需要使用的@One 注解(@Resultone=@One)()))
  6. many 需要使用的@Many 注解(@Resultmany=@many)()))
  • @One 注解(一对一),代替了 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
  1. @Result(column="列名",property="属性名",one=@One(select="指定用来多表查询的 sqlmapper"))
  • @Many 注解(一对多) ,代替了 标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合
    注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType(一般
    为 ArrayList) 但是注解中可以不定义;
  1. @Result(property="",column="",many=@Many(select=""))

3.2使用注解实现一对一复杂关系映射及延迟加载

3.2.1需求
  1. 查询账户(Account)信息并且关联查询用户(User)信息。
  2. 先查询账户(Account)信息,当我们需要用到用户(User)信息时再查询用户(User)信息。

3.2.2实现
  • User.java
  1. public class User implements Serializable{
  2. private int uid;
  3. private String username;// 用户姓名
  4. private String sex;// 性别
  5. private Date birthday;// 生日
  6. private String address;// 地址
  7. }
  • Account.java
  1. public class Account {
  2. private Integer aid;
  3. private Integer uid;
  4. private Double money;
  5. //表达关系:1个用户对应1个账户
  6. private User user;
  7. }
  • AccountDao.java

MyBatis_02 - 图6

  1. package com.itheima.dao;
  2. import com.itheima.pojo.Account;
  3. import org.apache.ibatis.annotations.One;
  4. import org.apache.ibatis.annotations.Result;
  5. import org.apache.ibatis.annotations.Results;
  6. import org.apache.ibatis.annotations.Select;
  7. import java.util.List;
  8. /**
  9. * 包名:com.itheima.dao
  10. *
  11. * @author Leevi
  12. * 日期2020-07-30 10:03
  13. * 一对一查询的两步
  14. * 1. 根据aid查询账户信息
  15. * 2. 根据uid查询用户信息,将查询到的用户信息设置到account中
  16. */
  17. public interface AccountDao {
  18. @Results(id="accountUserMap",value = {
  19. @Result(column = "uid",property = "uid"),
  20. @Result(property = "user",column = "uid",one = @One(select = "com.itheima.dao.UserDao.findByUid"))
  21. })
  22. @Select("select * from t_account where aid=#{aid}")
  23. Account findAccountByAid(int aid);
  24. }
  • UserDao.java
  1. public interface UserDao {
  2. /**
  3. * 根据id查询user
  4. * @param uid
  5. * @return
  6. */
  7. @Select("SELECT * FROM t_user WHERE uid = #{uid}")
  8. User findByUid(Integer uid);
  9. }
  • 测试
  1. public class DbTest {
  2. @Test
  3. public void test05(){
  4. Account account = accountDao.findAccountByAid(2);
  5. System.out.println(account);
  6. }
  7. }

3.3使用注解实现一对多复杂关系映射及延迟加载

3.3.1需求
  1. 完成加载用户对象时,查询该用户所拥有的账户信息。
  2. 等账户信息使用的时候再查询.

3.3.2实现
  • User.java
  1. public class User {
  2. private Integer uid;
  3. private String username;// 用户姓名
  4. private String sex;// 性别
  5. private Date birthday;// 生日
  6. private String address;// 地址
  7. //用于保存用户的多个账户信息
  8. private List<Account> accounts;
  9. }
  • UserDao.java
  1. package com.itheima.dao;
  2. import com.itheima.pojo.User;
  3. import org.apache.ibatis.annotations.*;
  4. import java.util.List;
  5. /**
  6. * 包名:com.itheima.dao
  7. *
  8. * @author Leevi
  9. * 日期2020-07-30 08:41
  10. */
  11. public interface UserDao {
  12. //为了测试一对多映射而写的方法
  13. @Results(id="userAccountMap",value = {
  14. @Result(column = "uid",property = "uid",id = true),
  15. //进行一对多的映射
  16. @Result(property = "accountList",column = "uid",many = @Many(select = "com.itheima.dao.AccountDao.findAccountListByUid"))
  17. })
  18. @Select("select * from t_user where uid=#{uid}")
  19. User findUserByUid(int id);
  20. }
  • AccountDao.java
  1. package com.itheima.dao;
  2. import com.itheima.pojo.Account;
  3. import org.apache.ibatis.annotations.One;
  4. import org.apache.ibatis.annotations.Result;
  5. import org.apache.ibatis.annotations.Results;
  6. import org.apache.ibatis.annotations.Select;
  7. import java.util.List;
  8. /**
  9. * 包名:com.itheima.dao
  10. *
  11. * @author Leevi
  12. * 日期2020-07-30 10:03
  13. */
  14. public interface AccountDao {
  15. @Select("select * from t_account where uid=#{uid}")
  16. List<Account> findAccountListByUid(int uid);
  17. }
  • 测试
  1. public class DbTest {
  2. @Test
  3. public void test06(){
  4. User user = userDao.findUserByUid(2);
  5. System.out.println(user);
  6. }
  7. }

4.小结