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


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

    1.1、问题说明

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

    二、sql初始化

    1. drop database if exists 20231101_mybatis;
    2. create database 20231101_mybatis;
    3. use 20231101_mybatis;
    4. DROP TABLE IF EXISTS `mybatis_user`;
    5. CREATE TABLE `mybatis_user` (
    6. `id` int NOT NULL AUTO_INCREMENT COMMENT '用户编号',
    7. `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
    8. `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',
    9. `account_non_expired` int NOT NULL DEFAULT 1 COMMENT '账户是否没有过期(1:没有过期、0:已过期)',
    10. `account_non_locked` int NOT NULL DEFAULT 1 COMMENT '账户是否没有被锁定(1:没有锁定、0:已锁定)',
    11. `credentials_non_expired` int NOT NULL DEFAULT 1 COMMENT '密码是否没有过期(1:没有过期、0:已过期)',
    12. `enabled` int NOT NULL DEFAULT 1 COMMENT '账户是否可用(1:可用、0:不可用)',
    13. PRIMARY KEY (`id`) USING BTREE
    14. ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;
    15. INSERT INTO `mybatis_user` VALUES (1, 'root', 'root123',1,1,1,1);
    16. INSERT INTO `mybatis_user` VALUES (2, 'admin', 'admin123',1,1,1,1);
    17. INSERT INTO `mybatis_user` VALUES (3, 'user', 'user123',1,1,1,1);
    18. DROP TABLE IF EXISTS `mybatis_role`;
    19. CREATE TABLE `mybatis_role` (
    20. `id` int NOT NULL AUTO_INCREMENT COMMENT '角色编号',
    21. `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色名称(英文)',
    22. `name_zh` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色名称(中文)',
    23. PRIMARY KEY (`id`) USING BTREE
    24. ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '角色表' ROW_FORMAT = DYNAMIC;
    25. INSERT INTO `mybatis_role` VALUES (1, 'dba', '数据库管理员');
    26. INSERT INTO `mybatis_role` VALUES (2, 'admin', '超级管理员');
    27. INSERT INTO `mybatis_role` VALUES (3, 'user', '用户');
    28. DROP TABLE IF EXISTS `mybatis_user_role`;
    29. CREATE TABLE `mybatis_user_role` (
    30. `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
    31. `u_id` int NULL DEFAULT NULL COMMENT '用户ID',
    32. `r_id` int NULL DEFAULT NULL COMMENT '角色ID',
    33. PRIMARY KEY (`id`) USING BTREE
    34. ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户角色关联表' ROW_FORMAT = DYNAMIC;
    35. INSERT INTO `mybatis_user_role` VALUES (1, 1, 1);
    36. INSERT INTO `mybatis_user_role` VALUES (2, 1, 2);
    37. INSERT INTO `mybatis_user_role` VALUES (3, 2, 2);
    38. 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

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework.bootgroupId>
    4. <artifactId>spring-boot-starter-webartifactId>
    5. dependency>
    6. <dependency>
    7. <groupId>org.springframework.bootgroupId>
    8. <artifactId>spring-boot-devtoolsartifactId>
    9. <scope>runtimescope>
    10. <optional>trueoptional>
    11. dependency>
    12. <dependency>
    13. <groupId>org.springframework.bootgroupId>
    14. <artifactId>spring-boot-starter-testartifactId>
    15. <scope>testscope>
    16. dependency>
    17. <dependency>
    18. <groupId>org.springframework.bootgroupId>
    19. <artifactId>spring-boot-starter-securityartifactId>
    20. dependency>
    21. <dependency>
    22. <groupId>com.baomidougroupId>
    23. <artifactId>mybatis-plus-boot-starterartifactId>
    24. <version>3.4.1version>
    25. dependency>
    26. <dependency>
    27. <groupId>mysqlgroupId>
    28. <artifactId>mysql-connector-javaartifactId>
    29. <version>8.0.26version>
    30. dependency>
    31. <dependency>
    32. <groupId>com.alibabagroupId>
    33. <artifactId>druid-spring-boot-starterartifactId>
    34. <version>1.1.21version>
    35. dependency>
    36. <dependency>
    37. <groupId>org.projectlombokgroupId>
    38. <artifactId>lombokartifactId>
    39. <optional>trueoptional>
    40. dependency>
    41. <dependency>
    42. <groupId>junitgroupId>
    43. <artifactId>junitartifactId>
    44. <version>4.13.2version>
    45. <scope>testscope>
    46. dependency>
    47. <dependency>
    48. <groupId>com.alibabagroupId>
    49. <artifactId>fastjsonartifactId>
    50. <version>1.2.76version>
    51. dependency>
    52. <dependency>
    53. <groupId>org.apache.commonsgroupId>
    54. <artifactId>commons-collections4artifactId>
    55. <version>4.3version>
    56. dependency>
    57. <dependency>
    58. <groupId>org.apache.commonsgroupId>
    59. <artifactId>commons-lang3artifactId>
    60. <version>3.11version>
    61. dependency>
    62. <dependency>
    63. <groupId>cn.hutoolgroupId>
    64. <artifactId>hutool-allartifactId>
    65. <version>5.7.22version>
    66. dependency>
    67. <dependency>
    68. <groupId>com.fasterxml.jackson.coregroupId>
    69. <artifactId>jackson-databindartifactId>
    70. <version>2.12.1version>
    71. dependency>
    72. dependencies>

    4.2、UserDO

    1. @TableName("mybatis_user")
    2. @AllArgsConstructor
    3. @NoArgsConstructor
    4. @Accessors(chain = true)
    5. @ToString
    6. public class UserDO implements UserDetails {
    7. /**
    8. * 主键
    9. */
    10. private Long id;
    11. /**
    12. * 用户名
    13. */
    14. private String username;
    15. /**
    16. * 密码
    17. */
    18. private String password;
    19. /**
    20. * 账户是否没有过期
    21. */
    22. private Boolean accountNonExpired;
    23. /**
    24. * 账户是否没有被锁定
    25. */
    26. private Boolean accountNonLocked;
    27. /**
    28. * 密码是否没有过期
    29. */
    30. private Boolean credentialsNonExpired;
    31. /**
    32. * 账户是否可用
    33. */
    34. private Boolean enabled;
    35. /**
    36. * 角色
    37. */
    38. @TableField(exist = false)
    39. private List roles;
    40. @Override
    41. public Collectionextends GrantedAuthority> getAuthorities() {
    42. List authorities = new ArrayList<>();
    43. for (RoleDO role : getRoles()) {
    44. authorities.add(new SimpleGrantedAuthority(role.getName()));
    45. }
    46. return authorities;
    47. }
    48. public Long getId() {
    49. return id;
    50. }
    51. public void setId(Long id) {
    52. this.id = id;
    53. }
    54. public void setUsername(String username) {
    55. this.username = username;
    56. }
    57. @Override
    58. public String getUsername() {
    59. return username;
    60. }
    61. public void setPassword(String password) {
    62. this.password = password;
    63. }
    64. @Override
    65. public String getPassword() {
    66. return password;
    67. }
    68. public void setAccountNonExpired(Boolean accountNonExpired) {
    69. this.accountNonExpired = accountNonExpired;
    70. }
    71. @Override
    72. public boolean isAccountNonExpired() {
    73. return accountNonExpired;
    74. }
    75. public void setAccountNonLocked(Boolean accountNonLocked) {
    76. this.accountNonLocked = accountNonLocked;
    77. }
    78. @Override
    79. public boolean isAccountNonLocked() {
    80. return accountNonLocked;
    81. }
    82. public void setCredentialsNonExpired(Boolean credentialsNonExpired) {
    83. this.credentialsNonExpired = credentialsNonExpired;
    84. }
    85. @Override
    86. public boolean isCredentialsNonExpired() {
    87. return credentialsNonExpired;
    88. }
    89. public void setEnabled(Boolean enabled) {
    90. this.enabled = enabled;
    91. }
    92. @Override
    93. public boolean isEnabled() {
    94. return enabled;
    95. }
    96. public List getRoles() {
    97. return roles;
    98. }
    99. public void setRoles(List roles) {
    100. this.roles = roles;
    101. }
    102. }

    4.3、RoleDO

    1. @TableName("mybatis_role")
    2. @Data
    3. @AllArgsConstructor
    4. @NoArgsConstructor
    5. @Accessors(chain = true)
    6. public class RoleDO implements Serializable {
    7. /**
    8. * 角色id
    9. */
    10. @TableField(value = "rId")
    11. private Long id;
    12. /**
    13. * 角色名称(英文名称)
    14. */
    15. private String name;
    16. /**
    17. * 角色名称(中文名称)
    18. */
    19. private String nameZh;
    20. }

    4.3、UserRoleDO

    1. @TableName("mybatis_user_role")
    2. @Data
    3. @AllArgsConstructor
    4. @NoArgsConstructor
    5. @Accessors(chain = true)
    6. public class UserRoleDO implements Serializable {
    7. /**
    8. * 主键
    9. */
    10. private Long id;
    11. /**
    12. * 用户id
    13. */
    14. private Long uId;
    15. /**
    16. * 角色id
    17. */
    18. private Long rId;
    19. }

    4.4、UserMapper

    1. public interface UserMapper extends BaseMapper {
    2. /**
    3. * 根据用户名查询用户
    4. * @param username
    5. * @return
    6. */
    7. UserDO loadUserByUsername(String username);
    8. }

    4.5、UserMapper.xml

    1. mapper
    2. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    4. <mapper namespace="org.star.mapper.UserMapper">
    5. <resultMap id="BaseResultMap" type="userDO">
    6. <id property="id" column="id"/>
    7. <result property="username" column="username"/>
    8. <result property="password" column="password"/>
    9. <result property="accountNonExpired" column="account_non_expired"/>
    10. <result property="accountNonLocked" column="account_non_locked"/>
    11. <result property="credentialsNonExpired" column="credentials_non_expired"/>
    12. <result property="enabled" column="enabled"/>
    13. <collection property="roles" ofType="roleDO">
    14. <id property="id" column="id"/>
    15. <result property="name" column="name"/>
    16. <result property="nameZh" column="name_zh"/>
    17. collection>
    18. resultMap>
    19. <select id="loadUserByUsername" resultMap="BaseResultMap">
    20. select mu.id, mu.username, mr.`name`, mr.name_zh,mr.id
    21. from mybatis_user mu
    22. left join mybatis_user_role mur on mu.id = mur.u_id
    23. left join mybatis_role mr on mr.id = mur.r_id
    24. where mu.username = #{username}
    25. select>
    26. mapper>

    五、测试

    5.1、Navicat测试(正常)

    1. SELECT
    2. mu.id,
    3. mu.username,
    4. mr.`name`,
    5. mr.name_zh
    6. FROM
    7. mybatis_user mu
    8. LEFT JOIN mybatis_user_role mur ON mu.id = mur.u_id
    9. LEFT JOIN mybatis_role mr ON mr.id = mur.r_id
    10. WHERE
    11. 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

  • 相关阅读:
    http和https的区别、什么是对称密钥,什么是非对称密钥
    数据填报系统究竟是买还是自研呢?_光点科技
    C#多线程(三)线程高级篇
    【ONE·C++ || 网络基础(二)】
    公司真实Java面试题泄露
    流程设计的基本步骤
    python数据分析及可视化(六)Pandas的对齐运算、混合运算、统计函数、排序函数、处理缺失值及数据的存储与读取
    Linux环境(Ubuntu)上的防火墙工具使用方法
    哈达玛矩阵与克罗内克积
    探索 SOCKS5 代理在跨境电商中的网络安全应用
  • 原文地址:https://blog.csdn.net/HelloWorld20161112/article/details/134363798