系列八、Mybatis一对多查询,只查询出了一条记录

一、Mybatis一对多查询,只查询出了一条记录

1.1、问题说明

        典型的权限管理框架的数据库表中,一般会存在这样3种角色的表,即用户表、角色表、用户角色关联表,表设计好之后,往这三张表中初始化了一些测试数据,现在有一个需求通过用户名查询用户的id、username、name、nameZh,在Navicat等工具中查询能够正常查询出来,但是使用mapper去查却只返回一条数据。

二、sql初始化

drop database if exists 20231101_mybatis;
create database 20231101_mybatis;
use 20231101_mybatis;

DROP TABLE IF EXISTS `mybatis_user`;
CREATE TABLE `mybatis_user`  (
                                 `id` int NOT NULL AUTO_INCREMENT COMMENT '用户编号',
                                 `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
                                 `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',
                                 `account_non_expired` int NOT NULL DEFAULT 1 COMMENT '账户是否没有过期(1:没有过期、0:已过期)',
                                 `account_non_locked` int NOT NULL DEFAULT 1 COMMENT '账户是否没有被锁定(1:没有锁定、0:已锁定)',
                                 `credentials_non_expired` int NOT NULL DEFAULT 1 COMMENT '密码是否没有过期(1:没有过期、0:已过期)',
                                 `enabled` int NOT NULL DEFAULT 1 COMMENT '账户是否可用(1:可用、0:不可用)',
                                 PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;

INSERT INTO `mybatis_user` VALUES (1, 'root', 'root123',1,1,1,1);
INSERT INTO `mybatis_user` VALUES (2, 'admin', 'admin123',1,1,1,1);
INSERT INTO `mybatis_user` VALUES (3, 'user', 'user123',1,1,1,1);

DROP TABLE IF EXISTS `mybatis_role`;
CREATE TABLE `mybatis_role`  (
                                 `id` int NOT NULL AUTO_INCREMENT COMMENT '角色编号',
                                 `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色名称(英文)',
                                 `name_zh` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色名称(中文)',
                                 PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色表' ROW_FORMAT = DYNAMIC;

INSERT INTO `mybatis_role` VALUES (1, 'dba', '数据库管理员');
INSERT INTO `mybatis_role` VALUES (2, 'admin', '超级管理员');
INSERT INTO `mybatis_role` VALUES (3, 'user', '用户');

DROP TABLE IF EXISTS `mybatis_user_role`;
CREATE TABLE `mybatis_user_role`  (
                                      `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
                                      `u_id` int NULL DEFAULT NULL COMMENT '用户ID',
                                      `r_id` int NULL DEFAULT NULL COMMENT '角色ID',
                                      PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户角色关联表' ROW_FORMAT = DYNAMIC;

INSERT INTO `mybatis_user_role` VALUES (1, 1, 1);
INSERT INTO `mybatis_user_role` VALUES (2, 1, 2);
INSERT INTO `mybatis_user_role` VALUES (3, 2, 2);
INSERT INTO `mybatis_user_role` VALUES (4, 3, 3);

三、表结构

3.1、mybatis_user

3.2、mybatis_role

3.3、mybatis_user_role

四、代码

4.1、pom

<dependencies>
	<!-- spring-boot -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
		<scope>runtime</scope>
		<optional>true</optional>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-security</artifactId>
	</dependency>

	<!-- 数据源 -->
	<dependency>
		<groupId>com.baomidou</groupId>
		<artifactId>mybatis-plus-boot-starter</artifactId>
		<version>3.4.1</version>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>8.0.26</version>
	</dependency>
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid-spring-boot-starter</artifactId>
		<version>1.1.21</version>
	</dependency>

	<!-- 工具 -->
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<optional>true</optional>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.13.2</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>fastjson</artifactId>
		<version>1.2.76</version>
	</dependency>
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-collections4</artifactId>
		<version>4.3</version>
	</dependency>
	<dependency>
		<groupId>org.apache.commons</groupId>
		<artifactId>commons-lang3</artifactId>
		<version>3.11</version>
	</dependency>
	<dependency>
		<groupId>cn.hutool</groupId>
		<artifactId>hutool-all</artifactId>
		<version>5.7.22</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.12.1</version>
	</dependency>

</dependencies>

4.2、UserDO

@TableName("mybatis_user")
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString
public class UserDO implements UserDetails {
    /**
     * 主键
     */
    private Long id;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 账户是否没有过期
     */
    private Boolean accountNonExpired;

    /**
     * 账户是否没有被锁定
     */
    private Boolean accountNonLocked;

    /**
     * 密码是否没有过期
     */
    private Boolean credentialsNonExpired;

    /**
     * 账户是否可用
     */
    private Boolean enabled;

    /**
     * 角色
     */
    @TableField(exist = false)
    private List<RoleDO> roles;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {

        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (RoleDO role : getRoles()) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }
    @Override
    public String getUsername() {
        return username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String getPassword() {
        return password;
    }

    public void setAccountNonExpired(Boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }
    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    public void setAccountNonLocked(Boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }
    @Override
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    public void setCredentialsNonExpired(Boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }

    public List<RoleDO> getRoles() {
        return roles;
    }

    public void setRoles(List<RoleDO> roles) {
        this.roles = roles;
    }
}

4.3、RoleDO

@TableName("mybatis_role")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class RoleDO implements Serializable {
    /**
     * 角色id
     */
    @TableField(value = "rId")
    private Long id;

    /**
     * 角色名称(英文名称)
     */
    private String name;

    /**
     * 角色名称(中文名称)
     */
    private String nameZh;

}

4.3、UserRoleDO

@TableName("mybatis_user_role")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class UserRoleDO implements Serializable {

    /**
     * 主键
     */
    private Long id;

    /**
     * 用户id
     */
    private Long uId;

    /**
     * 角色id
     */
    private Long rId;

}

4.4、UserMapper

public interface UserMapper extends BaseMapper<UserDO> {

    /**
     * 根据用户名查询用户
     * @param username
     * @return
     */
    UserDO loadUserByUsername(String username);
}

4.5、UserMapper.xml

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.star.mapper.UserMapper">

    <resultMap id="BaseResultMap" type="userDO">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="accountNonExpired" column="account_non_expired"/>
        <result property="accountNonLocked" column="account_non_locked"/>
        <result property="credentialsNonExpired" column="credentials_non_expired"/>
        <result property="enabled" column="enabled"/>
        <collection property="roles" ofType="roleDO">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="nameZh" column="name_zh"/>
        </collection>
    </resultMap>

    <select id="loadUserByUsername" resultMap="BaseResultMap">
        select mu.id, mu.username, mr.`name`, mr.name_zh,mr.id
        from mybatis_user mu
                 left join mybatis_user_role mur on mu.id = mur.u_id
                 left join mybatis_role mr on mr.id = mur.r_id
        where mu.username = #{username}
    </select>

</mapper>

五、测试

5.1、Navicat测试(正常)

SELECT
	mu.id,
	mu.username,
	mr.`name`,
	mr.name_zh 
FROM
	mybatis_user mu
	LEFT JOIN mybatis_user_role mur ON mu.id = mur.u_id
	LEFT JOIN mybatis_role mr ON mr.id = mur.r_id 
WHERE
	mu.username = 'root'

5.2、代码测试(异常)

        同样的查询条件,Navicat中查询正常,代码中查询不正常,原因是什么呢? 多条的数据只显示一条,是因为字段名相同,两张表的主键都是id,就只会显示一条数据,只需要把多条数据的表id的column修改成别名就可以了。如下所示:

5.3、问题解决

5.3.1、修改UserMapper.xml的映射信息和查询信息

5.3.2、再次查询(正常) 

六、参考 

https://www.cnblogs.com/damugua/p/17046724.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/136241.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

stm32超声波测距不准的解决方法(STM32 delay_us()产生1us)及stm32智能小车超声波测距代码(C语言版本)

首先要说明一下原理&#xff1a;使用stm32无法准确产生1us的时间&#xff0c;但是超声波测距一定要依赖时间&#xff0c;时间不准&#xff0c;距离一定不准&#xff0c;这是要肯定的&#xff0c;但是在不准确的情况下&#xff0c;要测量一个比较准确的时间&#xff0c;那么只能…

混沌系统在图像加密中的应用(基于哈密顿能量函数的混沌系统构造1.3)

混沌系统在图像加密中的应用&#xff08;基于哈密顿能量函数的混沌系统构造1.3&#xff09; 前言一类三维非哈密顿系统的构造与动态特性分析1.相关理论基础2.类Nos-Hoove系统构造的思路及实现3.基于哈密顿能量理论的Nos-Hoove系统的分析与仿真3.1 平衡点分析3.2 不同强度激励下…

C语言从入门到精通之【数据类型和关键字】

数据类型在程序使用之前已经预先设定好了&#xff0c;在整个程序的运行过程中没有变化&#xff0c;这些称为常量&#xff08;constant&#xff09;。其他数据类型在程序运行期间可能会改变或被赋值&#xff0c;这些称为变量&#xff08;variable&#xff09;。 变量类型有几种…

(二十七)ATP应用测试平台——基于mybatisplus和aop切面实现数据权限隔离的案例实战

前言 在实际项目开发中&#xff0c;我们经常会用到俩种权限&#xff0c;一种是功能权限&#xff0c;一种是数据权限。功能权限主要是用来限制用户的操作&#xff0c;而数据权限是限制用户能查看到哪些数据。功能权限我们可以使用流行的框架shiro或者spring-security实现&#…

C语言--求一个 3 X 3 的整型矩阵对角线元素之和

一.题目描述 求一个 3 X 3 的整型矩阵对角线元素之和 二.代码实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() {int arr[3][3] { 0 };for (int i 0;i < 3;i){for (int j 0;j < 3;j){ printf("请输入数字&#xff1a;");scanf(&…

暴力递归转动态规划(十五)

题目 给定一个正数n&#xff0c;求n的裂开方法数&#xff0c; 规定&#xff1a;后面的数不能比前面的数小 比如4的裂开方法有&#xff1a; 1111、112、13、22、04 。 5种&#xff0c;所以返回5 暴力递归 用暴力递归方法进行尝试&#xff0c;整体思路是这样&#xff1a; 暴力递…

RcppRcppEigen学习材料推荐

目录 一Rcpp和RcppEigen包 二Rcpp学习材料来源 三Rcpp&RcppEigen学习材料汇总 一Rcpp和RcppEigen包 目前已有RcppEigen包&#xff0c;因此直接下载安装RcppEigen包即可&#xff0c;不需要在Eigen官网下载安装。即不需要安装任何关于C的软件&#xff0c;直接基于R进行C相…

Java入门篇 之 补 类与对象

本篇碎碎念&#xff1a;每个人的想法都不一样&#xff0c;不要强求&#xff0c;顺其自然&#xff0c;要相信&#xff0c;一切都在向好的方面前进&#xff01;&#xff01;&#xff01;&#xff01; 今日份励志文案:山海的浩瀚&#xff0c;宇宙的浪漫&#xff0c;都在我内心翻腾…

【编程语言发展史】Python的起源和发展历史

目录 Python的起源 Python的发展历史 Python的生态系统和应用领域 Python的社区和发展模式 Python的未来趋势和挑战 Python是一门广受欢迎的高级编程语言&#xff0c;其起源和发展历史自20世纪末至今&#xff0c;经历了多个版本的迭代和社区的广泛参与。以下是关于Python的…

电子工程师的焊接技法总结

基础学习视频如下&#xff1a; 1 老司机焊接纯干货分享&#xff0c;让你焊接不迷路&#xff0c;很适合零基础小白_哔哩哔哩_bilibili 焊接常用工具 1 焊锡丝 按照粗细来分的话&#xff0c;有粗焊锡&#xff0c;有细焊锡&#xff0c;细焊锡一般适合比较精细的焊接。 按照是否含铅…

在使用Vuex时,5个方法让你保证数据的更新及时性

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Langchain-Chatchat环境安装

目录 一、简介 二、环境安装 三、使用Langchain-Chatchat 3.1、下载模型 3.2、设置配置文件 3.3、执行 一、简介 基于 ChatGLM 等大语言模型与 Langchain 等应用框架实现&#xff0c;开源、可离线部署的检索增强生成(RAG)大模型知识库项目。 &#x1f916;️ 一种利用 l…

数据结构:AVLTree的插入和删除的实现

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》 文章目录 前言一、AVLTree二、AVLTree的插入插入新增节点调整平衡因子旋转左单旋(新增节点位于较高右子树的右侧)右单旋(新增节点位于较高左子树的左侧)右左双旋(新增节点在较高右子树的左子…

【2011年数据结构真题】

41题 41题解答&#xff1a; &#xff08;1&#xff09;图 G 的邻接矩阵 A 如下所示&#xff1a; 由题意得&#xff0c;A为上三角矩阵&#xff0c;在上三角矩阵A[6][6]中&#xff0c;第1行至第5行主对角线上方的元素个数分别为5, 4, 3, 2, 1 用 “ 平移” 的思想&#xff0c;…

ENVI IDL:如何将txt文本文件转化为GeoTIFF文件?

01 前言 此处的文本文件形式如下&#xff1a; 里面包含了众多点位信息&#xff08;不是站点数据&#xff09;&#xff0c;我们需要依据上述点的经纬度信息放到对应位置的像素点位置&#xff0c;放置完后如下&#xff1a; 可以发现&#xff0c;还存在部分缺失值&#xff0c;我们…

Qt实现TCP调试助手 - 简述如何在Qt中实现TCP多并发

简介 软件开发中&#xff0c;可能经常会用到TCP调试工具。本人使用QT开发了一款TCP调试工具&#xff0c;方便大家使用。本文章主要介绍下&#xff0c;该工具的功能&#xff0c;以及如何在Qt中实现TCP服务器的并发。 界面展示 安装界面 桌面图标。安装后会生成桌面图标&#…

【操作系统】1.1 操作系统的基础概念、功能和目标以及特性

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

手机开机入网流程 KPI接通率和掉线率

今天我们来学习手机开机入网流程是怎么样的。以及RRC连接和重建流程(和博主之前讲TCP三次握手&#xff0c;四次挥手原理很相似)是什么样的&#xff0c;还有天线的KPI指标都包括什么&#xff0c;是不是很期待啊~ 目录 手机开机入网流程 ATTACH/RRC连接建立过程 KPI接通率和掉…

MongoDB基础知识~

引入MongoDB&#xff1a; 在面对高并发&#xff0c;高效率存储和访问&#xff0c;高扩展性和高可用性等的需求下&#xff0c;我们之前所学习过的关系型数据库(MySql,sql server…)显得有点力不从心&#xff0c;而这些需求在我们的生活中也是随处可见的&#xff0c;例如在社交中…

node插件express(路由)的插件使用(二)——cookie 和 session的基本使用区别

文章目录 前言一、express 框架中的 cookie0、cookie的介绍和作用1. 设置cookie2.删除cookie3.获取cookie&#xff08;1&#xff09;安装cookie-parser&#xff08;2&#xff09;导入cookie-parser&#xff08;3&#xff09;注册中间件&#xff08;4&#xff09;获取cookie&…