九点钟☆方向

记录成长点滴

欢迎来到我的个人博客~


Mybatis笔记(八) Mybatis中的多表查询

目录

表之间的关系

  1. 一对多:用户和订单的关系
  2. 多对一:订单和用户的关系
  3. 一对一:人和身份证号的关系
  4. 多对多:老师和学生的关系

特例:如果拿出每一个订单他都只能属于一个用户,所以Mybatis把多对一看成一对一

Mybatis 多表查询

本次案例主要以最为简单的用户和账户的模型来分析 Mybatis 多表关系。用户为 User 表,账户为 Account 表。一个用户(User)可以有多个账户(Account)。具体关系如下:

9

步骤:

  1. 建立两张表,用户表和账户表,让用户表和账户表有一对多的关系需要用外键关联,外键建立在账户表
  2. 建立两个实体类,用户类和账户类,实体类也要体现一对多的关系。
  3. 建立两个配置文件,用户配置文件和账户配置文件
  4. 实现配置,当查询用户时得到账户信息,查询账户时得到用户信息

一对一查询(多对一)

需求:查询所有账户信息,关联查询下单用户信息。 注意:因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如 果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。

方式一:定义专门的类(AccountUser )作为输出类型,其中定义了sql语句查询结果集的所有字段
  1. 定义账户信息的实体类Account:

    /**
    *
    * <p>Title: Account</p>
    * <p>Description: 账户的实体类</p>
    */
    public class Account implements Serializable {
        private Integer id;
        private Integer uid;
        private Double money;
        //生成set/get
    }
    
  2. 定义 AccountUser 类

    //定义AccountUser类中要包含账户信息同时还要包含用户信息,可以让其继承account类
    public class AccountUser extends Account implements Serializable {
        private String username;
        private String address;
      	//生成set/get
    }
    
  3. 定义账户的持久层 Dao 接口

    public interface IAccountMapper {
        /**
        * 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
        * @return
        */
    	List<AccountUser> findAll();
    }
    
  4. 定义 IAccountMapper.xml 文件中的查询配置信息

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mg.dao.IAccountMapper">
        <!-- 配置查询所有操作  resultType可以使用别名-->
        <select id="findAll" resultType="accountuser">
        	select a.*,u.username,u.address from account a,user u where a.uid =u.id;
        </select>
    </mapper>
       
    注意:因为上面查询的结果中包含了账户信息同时还包含了用户信息,所以我们的返回值类型 returnType
    的值设置为 AccountUser 类型,这样就可以接收账户信息和用户信息了。
    
方式二:使用 resultMap

定义专门的 resultMap 用于映射一对一查询结果。通过面向对象的(has a)关系可以得知,我们可以在 Account 类中加入一个 User 类的对象来代表这个账户是哪个用户的。

  1. 定义账户信息Account类

    public class Account implements Serializable {
        private Integer id;
        private Integer uid;
        private Double money;
        //加入User类的引用,单个关系
    	private User user;
        //生成set/get
    }
    
  2. 用户类User

    public class User implements Serializable {
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
        private List<Account> accounts;
        //生成set/get
    }
    
  3. 定义Dao接口

    public interface IAccountMapper {
        /**
        * 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
        * @return
        */
    	List<Account> findAll();
    }
       
    注意第二种方式将返回值改 为了 Account 类型
    因为 Account 类中包含了一个 User 类的对象它可以封装账户所对应的用户信息
    
  4. 定义 IAccountMapper.xml 文件中的查询配置信息

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mg.dao.IAccountMapper">
        <!-- 建立对应关系 -->
        <!-- type的值可以写别名 -->
        <resultMap type="account" id="accountMap">
            <id column="aid" property="id"/>
            <result column="uid" property="uid"/>
            <result column="money" property="money"/>
            <!--association标签:  用于单个关系属性    javaType:指定属性的类型,可以使用别名-->
            <association property="user" javaType="user">
                <id column="id" property="id"/>
                <result column="username" property="username"/>
                <result column="sex" property="sex"/>
                <result column="birthday" property="birthday"/>
                <result column="address" property="address"/>
            </association>
        </resultMap>
           
        <!--resultMap直接引用上面定义的即可-->
        <select id="findAll" resultMap="accountMap">
            select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
        </select>
    </mapper>
    

一对多查询

需求:查询所有用户信息及用户关联的账户信息。 分析:用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息 查询出来,我们想到了左外连接查询比较合适。

  1. 用户类User

    public class User implements Serializable {
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
        private List<Account> accounts;
        //生成set/get
    }
    
  2. 定义账户信息的实体类Account

    public class Account implements Serializable {
        private Integer id;
        private Integer uid;
        private Double money;
        //加入User类的引用,单个关系
    	private User user;
        //生成set/get
    }
    
  3. 定义DAO接口 IUserMapper

    /**
    * 查询所有用户,同时获取出每个用户下的所有账户信息
    * @return
    */
    List<User> findAll();
    
  4. 用户持久层映射配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mg.dao.IUserMapper">
        <resultMap type="user" id="userMap">
            <id column="id" property="id"></id>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <!-- collection 是用于建立一对多中集合属性的对应关系  ofType 用于指定集合元素的数据类型,可以使用别名-->
            <collection property="accounts" ofType="account">
                <id column="aid" property="id"/>
                <result column="uid" property="uid"/>
                <result column="money" property="money"/>
            </collection>
        </resultMap>
    <!-- 配置查询所有操作 -->
        <select id="findAll" resultMap="userMap">
            select u.*,a.id as aid ,a.uid,a.money 
            from user u 
            left outer join account a 
            on u.id =a.uid
        </select>
    </mapper>
       
    collection:部分定义了用户关联的账户信息。表示关联查询结果集
    property="accounts":关联查询的结果集存储在 User 对象的上哪个属性。
    ofType="account":指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
    

多对多查询

以角色Role 和用户 User 的多对多为例 。多对多关系其实我们看成是双向的一对多关系

用户与角色的关系模型 :

10

角色表

11

实现 Role 到 User 多对多

需求:实现查询所有对象并且加载它所分配的用户信息。 分析:查询角色我们需要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中 间表(USER_ROLE 表)才能关联到用户信息

  1. 编写角色实体类 Role

    public class Role implements Serializable {
        private Integer roleId;
        private String roleName;
        private String roleDesc;
        //多对多的关系映射:一个角色可以赋予多个用户
        private List<User> users;
        //生成set/get
    }
    
  2. User类

    public class User implements Serializable {
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
        //生成set/get
    }
    
  3. 编写 Role 持久层接口

    public interface IRoleMapper {
        /**
        * 查询所有角色
        * @return
        */
        List<Role> findAll();
    }
    
  4. 编写映射配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mg.dao.IRoleMapper">
        <!--定义 role 表的 ResultMap-->
        <resultMap id="roleMap" type="role">
            <id property="roleId" column="rid"></id>
            <result property="roleName" column="role_name"></result>
            <result property="roleDesc" column="role_desc"></result>
            <collection property="users" ofType="user">
                <id column="id" property="id"></id>
                <result column="username" property="username"></result>
                <result column="address" property="address"></result>
                <result column="sex" property="sex"></result>
                <result column="birthday" property="birthday"></result>
            </collection>
        </resultMap>
        <!--查询所有-->
        <select id="findAll" resultMap="roleMap">
            select u.*,r.id as rid,r.role_name,r.role_desc from role r
            left outer join user_role ur on r.id = ur.rid
            left outer join user u on u.id = ur.uid
        </select>
    </mapper>
    
    实现 User 到 Role 的多对多

    从 User 出发,我们也可以发现一个用户可以具有多个角色,这样用户到角色的关系也还是一对多关系。这样 我们就可以认为 User 与 Role 的多对多关系,可以被拆解成两个一对多关系来实现。

    User到Role的多对多和上面类似:

    1. User类

      public class User implements Serializable {
          private Integer id;
          private String username;
          private Date birthday;
          private String sex;
          private String address;
      	//加入Role的引用
          private List<Role> roles;
          //生成set/get
      }
      
    2. Role类

      public class Role implements Serializable {
          private Integer roleId;
          private String roleName;
          private String roleDesc;
          //生成set/get
      }
      
    3. dao接口

      public interface IUserMapper {
          List<User> findAll();
      }
      
    4. 映射配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.mg.dao.IUserMapper">
          <resultMap id="userMap" type="user">
              <id property="id" column="id"></id>
              <result property="username" column="username"></result>
              <result property="birthday" column="birthday"></result>
              <result property="sex" column="sex"></result>
              <result property="address" column="address"></result>
            
              <collection property="roles" ofType="role">
                  <id property="roleId" column="rid"></id>
                  <result property="roleName" column="role_name"></result>
                  <result property="roleDesc" column="role_desc"></result>
              </collection>
          </resultMap>
                
          <select id="findAll" resultMap="userMap">
              select u.*,r.id as rid,r.role_name,r.role_desc from user u
              left outer join user_role ur on u.id = ur.uid
              left outer join role r on r.id = ur.rid
          </select>
      </mapper>
      

总结:实体中谁建关系属性,对应的Mapper文件就要书写多表操作定义ResultMap

​ 如果是单个关系属性则使用

<association   property=""   javaType="">

​ 如果是集合关系属性则使用

<collection property="" ofType="">

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦