Mybatis 复杂查询(多对多、一对多、多对一)

我们知道,在 Mybatis 中完成单表查询是很容易的,而多表查询是 Mybatis 框架中的一个重难点,需熟练掌握。

1、多对多查询

用户和小组为多对多的关系,需求为:通过用户 id 查找其所有的小组信息

数据库设计如下:

在这里插入图片描述
实体类:

public class User {
    private int uId;
    private String uName;
    private List<Group> groupList;

一个 User 对应多个 Group ,用一个 List 存储

public class Group {
    private int gId;
    private String gName;
    private List<User> userList;

一个 User 对应多个 User,用一个 List 存储

public class UserGroup {
    private User user;
    private Group group;

中间表包含两个对象

实现需求:通过用户 id 查找其所有的小组信息

UserMapper 接口:

public interface UserMapper {
    List<Group> getGroupByUId(int uId);
}

UserMapper.xml:

    <select id="getGroupByUId" resultMap="userGroupMap">
        select u.uId, u.uName, g.gId, g.gName
        from `user` u,`group` g, uesr_group ug
        where g.gId = ug.gId and ug.uId = #{uId} and u.uId = #{uId};
    </select>

    <resultMap id="userGroupMap" type="com.ssm.pojo.Group">
        <id column="gId" property="gId"/>
        <result column="gName" property="gName"/>
        <collection property="userList" ofType="com.ssm.pojo.User">
            <id column="uId" property="uId"/>
            <result column="uName" property="uName"/>
        </collection>
    </resultMap>

由于需查询所有 Group 的信息,该方法返回 Group 集合

这里的 resutMap 类型为中间表实体对象 UserGroup ,它将两个表联系在一起

其实通过 collection 来处理集合对象的属性映射

数据库表测试数据:
在这里插入图片描述
查询结果(查找用户 id 为1的所有小组信息):

在这里插入图片描述
可以看到,小组信息以及用户信息都已经被正确地查询出来

2、 一对多查询

增加 Account 表,一个用户对应多个 Account

需求:查询指定用户所有的账户

数据库测试数据:
在这里插入图片描述

写法 1

实体类:

public class User {
    private int uId;
    private String uName;
    private List<Group> groupList;
    private List<Account> accountList;

一个 User 对应多个 Account,用一个 List 存储

public class Account {
    private int aId;
    private String aName;
    private User user;

一个 Account 对应一个 User 对象

UserMapper 接口:

public interface UserMapper {
    List<Group> getGroupByUId(int uId);
    List<Account> getAccountByUId(int uId);
}

UserMapper 实现:

    <select id="getAccountByUId" resultMap="userAccountMap">
        select a.aId, a.aName, u.uId, u.uName
        from user u, account a
        where u.uId = a.uId and u.uId = #{uId};
    </select>
    <resultMap id="userAccountMap" type="com.ssm.pojo.Account">
        <result column="aId" property="aId"/>
        <result column="aName" property="aName"/>
        <association property="user" javaType="com.ssm.pojo.User">
            <result column="uId" property="uId"/>
            <result column="uName" property="uName"/>
        </association>
    </resultMap>

查询结果:

在这里插入图片描述
写法1 以 Account(多的一方) 作为主表,即 resultMap 的类型为 Account,由于一个 Account 只对应一个 User,

所以在 resultMap 中 采用 assocation 引入 User,从而实现多表查询。

这种写法的特点在于结果有多行记录,将 Account 的属性直接列出,而集合中则为重复的 user 信息

写法 2

实体类:

public class User {
    private int uId;
    private String uName;
    private List<Group> groupList;
    private List<Account> accountList;
public class Account {
    private int aId;
    private String aName;
    private int uId;

UserMapper 接口:

public interface UserMapper {
    List<Group> getGroupByUId(int uId);
    List<Account> getAccountByUId(int uId);
    User getUserByUId(int uId);
}

该方法是通过返回 User(一对多中一的一方) ,在 User 中通过 collection 引入 Account 关联

UserMapper.xml 实现:

    <select id="getUserByUId" resultMap="userAccountMap">
        select a.aId, a.aName, u.uId, u.uName
        from user u, account a
        where u.uId = a.uId and u.uId = #{uId};
    </select>
    <resultMap id="userAccountMap" type="com.ssm.pojo.User">
        <result column="uId" property="uId"/>
        <result column="uName" property="uName"/>
        <collection property="accountList" ofType="com.ssm.pojo.Account">
            <result column="aId" property="aId"/>
            <result column="aName" property="aName"/>
        </collection>
    </resultMap>

测试结果:

在这里插入图片描述

写法2 以 User 作为主表,即 resultMap 的类型为 User,

由于一个 User 对应多个 Account,所以在 resultMap 中 采用 collectiion 引入 Account ,从而实现多表查询。

这种写法的特点在于结果只有一行记录,将 user 的属性直接列出,而集合中则为的 Account 信息。

3、多对一查询

需求:查询给定账户对应的用户

方式 1

实体类:

public class User {
    private int uId;
    private String uName;
    private List<Group> groupList;
    private List<Account> accountList;
public class Account {
    private int aId;
    private String aName;
    private int uId;

AccountMapper 接口:

public interface AccountMapper {
    User getUserByAId(int aId);
}

这里返回 User(多对一中一的一方),在 User 中通过 collection 引入 Account

AccountMapper.xml 实现:

    <select id="getUserByAId" resultMap="accountUserMap">
        select u.uId, u.uName, a.aId, a.aName
        from user u, account a
        where u.uId = a.uId and a.aId = #{aId}
    </select>
    <resultMap id="accountUserMap" type="com.ssm.pojo.User">
        <result column="uId" property="uId"/>
        <result column="uName" property="uName"/>
        <collection property="accountList" ofType="com.ssm.pojo.Account">
            <result column="aId" property="aId"/>
            <result column="aName" property="aName"/>
        </collection>
    </resultMap>

查询结果:
在这里插入图片描述

方式 2

实体类:

public class User {
    private int uId;
    private String uName;
    private List<Group> groupList;
    private List<Account> accountList;
public class Account {
    private int aId;
    private String aName;
    private User user;

AccountMapper 接口:

public interface AccountMapper {
    Account getAccountAndUser(int aId);
}

该方法返回 Account(多的一方),在 resultMap 中通过 association 引入 User 关联

AccountMapper.xml 实现:

    <select id="getAccountAndUser" resultMap="accountUserMap">
        select u.uId, u.uName, a.aId, a.aName
        from user u, account a
        where u.uId = a.uId and a.aId = #{aId}
    </select>
    <resultMap id="accountUserMap" type="com.ssm.pojo.Account">
        <result column="aId" property="aId"/>
        <result column="aName" property="aName"/>
        <association property="user" javaType="com.ssm.pojo.User">
            <result column="uId" property="uId"/>
            <result column="uName" property="uName"/>
        </association>
    </resultMap>

测试结果:
在这里插入图片描述

4、总结

首先,我们要需定义好实体类的属性以及 dao 的接口

如果映射的对象只有1个,采用 assocation + javaType,如果映射的对象为一个集合 List,则采用 connection + ofType

result 标签为结果集映射关系, column 对应数据库中的列名,property 对应实体类的属性名

resultMap 的类型可以选择一对多中多的一方或一的一方,,指定好其类型后,采用 assocation + javaType 或 connection + ofType 定义好对象关联映射即可。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值