Code前端首页关于Code前端联系我们

MyBatis教程:XML多表查询的基本使用

terry 2年前 (2023-09-25) 阅读数 54 #后端开发

1.多表查询

在上一篇博客中,我们举例说明的两个查询都是单表查询,但实际业务场景肯定需要多表。比如查询,现在有一个需求:

查询某个用户拥有的所有角色s。这个需求涉及到三个表:sys_user、sys_user_role、sys_role。如何实施?

首先在SysUserMapper接口中定义以下方法。

/**
 * 根据用户id获取角色信息
 *
 * @param userId
 * @return
 */
List<SysRole> selectRolesByUserId(Long userId);

然后打开对应的SysUserMapper.xml文件,添加如下select语句:

<select id="selectRolesByUserId" resultType="com.zwwhnly.mybatisaction.model.SysRole">
    SELECT r.id,
           r.role_name   roleName,
           r.enabled,
           r.create_by   createBy,
           r.create_time createTime
    FROM sys_user u
    INNER JOIN sys_user_role ur ON u.id = ur.user_id
    INNER JOIN sys_role r ON ur.role_id = r.id
    WHERE u.id = #{userId}
</select>

细心的读者可以发现,即使我们使用多表查询,resultType仍然设置为单表,即它只包含角色表信息。

如果我的希望查询也返回SysUser表中的用户名字段,我应该如何设置resultType?

方法一:直接在SysRole实体类中添加用户名字段。

private String userName;

public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

此时不需要更改 ResultType。

方法二:新建一个扩展类,并将用户名字段添加到扩展类中。

package com.zwwhnly.mybatisaction.model;

public class SysRoleExtend extends SysRole {
    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

此时resultType应更改为:com.zwwhnly.mybatisaction.model.SysRoleExtend。

该方法比较适合需要少量额外字段的场景。如果需要大量其他表的字段,可以使用方法3或4,我个人推荐使用方法4。

方法3:在SysRole实体类中添加一个SysUser类型的字段。

private SysUser sysUser;

public SysUser getSysUser() {
   return sysUser;
}

public void setSysUser(SysUser sysUser) {
    this.sysUser = sysUser;
}

此时不需要更改ResultType。

方法四(推荐):新建一个扩展类,并在扩展类中添加一个SysUser类型的字段。

书上推荐的是方法3。方法4是我认为最好的方法,因为实体类一般都是由工具自动生成的。添加字段后,很容易忘记并在以后覆盖它们。

package com.zwwhnly.mybatisaction.model;

public class SysRoleExtend extends SysRole {
    private SysUser sysUser;

    public SysUser getSysUser() {
        return sysUser;
    }

    public void setSysUser(SysUser sysUser) {
        this.sysUser = sysUser;
    }
}

此时resultType应更改为:com.zwwhnly.mybatisaction.model.SysRoleExtend。

此时xml中的查询语句如下。

<select id="selectRolesByUserId" resultType="com.zwwhnly.mybatisaction.model.SysRoleExtend">
    SELECT r.id,
           r.role_name   roleName,
           r.enabled,
           r.create_by   createBy,
           r.create_time createTime,
           u.user_name   "sysUser.userName",
           u.user_email   "sysUser.userEmail"
    FROM sys_user u
    INNER JOIN sys_user_role ur ON u.id = ur.user_id
    INNER JOIN sys_role r ON ur.role_id = r.id
    WHERE u.id = #{userId}
</select>

在SysUserMapperTest中添加测试代码如下。

@Test
public void testSelectRolesByUserId() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);

        List<SysRole> sysRoleList = sysUserMapper.selectRolesByUserId(1L);

        Assert.assertNotNull(sysRoleList);
        Assert.assertTrue(sysRoleList.size() > 0);
    } finally {
        sqlSession.close();
    }
}

运行此测试方法并输入日志如下。

DEBUG [main] - ==> 准备: SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime, u.user_name "sysUser.userName", "u.user_email " sysUser.userEmail" FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.id WHERE u.id = ? ==>主参数]DE:G 1 (长)

TRACE [main] -

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门