当前位置: 首页 > news >正文

MyBatis联合查询 - 注解篇

文章目录

  • 前言
  • 数据库表
  • 一对一关联查询
    • 方式一:
    • 方式二:
  • 一对多关联查询
    • 使用@Many注解
  • 多对多关联查询
    • 方式一:
    • 方式二:
  • 总结

前言

在日常开发中,我们经常需要查询多张表的数据,传统的XML配置方式虽然功能强大,但有时候显得比较繁琐。MyBatis的注解方式为我们提供了一种更简洁、更直观的解决方案 - 注解

数据库表

-- 用户表
CREATE TABLE user (id BIGINT PRIMARY KEY,name VARCHAR(50),email VARCHAR(100),dept_id BIGINT
);-- 部门表  
CREATE TABLE department (id BIGINT PRIMARY KEY,dept_name VARCHAR(50),location VARCHAR(100)
);

对应的实体类:

@Data
public class User {private Long id;private String name;private String email;private Long deptId;private Department department; 
}@Data
public class Department {private Long id;private String deptName;private String location;
}

一对一关联查询

方式一:

最常用的方式是直接在SQL中进行关联查询:

@Mapper
public interface UserMapper {@Select("SELECT *" + "FROM user u LEFT JOIN department d ON u.dept_id = d.id " +"WHERE u.id = #{id}")@Results({@Result(property = "id", column = "id"),@Result(property = "name", column = "name"),@Result(property = "email", column = "email"),@Result(property = "deptId", column = "dept_id"),@Result(property = "department.id", column = "dept_id"),@Result(property = "department.deptName", column = "dept_name"),@Result(property = "department.location", column = "location")})User getUserWithDept(Long id);
}

这种方式简单直接,一次查询就能获取所有需要的数据,性能比较好。

方式二:

如果你更喜欢分步查询的方式,可以使用@One注解:

@Mapper
public interface UserMapper {@Select("SELECT * FROM user WHERE id = #{id}")@Results({@Result(property = "id", column = "id"),@Result(property = "name", column = "name"),@Result(property = "email", column = "email"),@Result(property = "deptId", column = "dept_id"),@Result(property = "department", column = "dept_id",one = @One(select = "com.example.mapper.DepartmentMapper.getDeptById"))})User getUserWithDept2(Long id);
}@Mapper
public interface DepartmentMapper {@Select("SELECT * FROM department WHERE id = #{id}")Department getDeptById(Long id);
}

这种方式会执行两次SQL查询,先查用户信息,再根据部门ID查询部门信息。虽然查询次数多了,但逻辑更清晰,复用性也更好。

一对多关联查询

假设我们要查询部门及其下属的所有员工:

@Data
public class Department {private Long id;private String deptName;private String location;private List<User> users; 
}

使用@Many注解

@Mapper
public interface DepartmentMapper {@Select("SELECT * FROM department WHERE id = #{id}")@Results({@Result(property = "id", column = "id"),@Result(property = "deptName", column = "dept_name"),@Result(property = "location", column = "location"),@Result(property = "users", column = "id",many = @Many(select = "com.example.mapper.UserMapper.getUsersByDeptId"))})Department getDeptWithUsers(Long id);
}@Mapper
public interface UserMapper {@Select("SELECT * FROM user WHERE dept_id = #{deptId}")List<User> getUsersByDeptId(Long deptId);
}

多对多关联查询

多对多关系是最复杂的关联关系,通常需要一张中间表来维护关系。我们以用户和角色的关系为例:

-- 角色表
CREATE TABLE role (id BIGINT PRIMARY KEY,role_name VARCHAR(50),description VARCHAR(200)
);-- 用户角色关联表
CREATE TABLE user_role (user_id BIGINT,role_id BIGINT,PRIMARY KEY (user_id, role_id)
);

对应的实体类:

@Data
public class User {private Long id;private String name;private String email;private Long deptId;private Department department;private List<Role> roles; 
}@Data
public class Role {private Long id;private String roleName;private String description;private List<User> users;
}

方式一:

@Mapper
public interface UserMapper {@Select("SELECT * " +"FROM user u " +"LEFT JOIN user_role ur ON u.id = ur.user_id " +"LEFT JOIN role r ON ur.role_id = r.id " +"WHERE u.id = #{userId}")@Results({@Result(property = "id", column = "id"),@Result(property = "name", column = "name"),@Result(property = "email", column = "email"),@Result(property = "roles", column = "id",many = @Many(select = "com.example.mapper.RoleMapper.getRolesByUserId"))})User getUserWithRoles(Long userId);
}@Mapper
public interface RoleMapper {@Select("SELECT r.* FROM role r " +"INNER JOIN user_role ur ON r.id = ur.role_id " +"WHERE ur.user_id = #{userId}")List<Role> getRolesByUserId(Long userId);
}

方式二:

@Mapper
public interface RoleMapper {@Select("SELECT r.id, r.role_name, r.description " +"FROM role r WHERE r.id = #{roleId}")@Results({@Result(property = "id", column = "id"),@Result(property = "roleName", column = "role_name"),@Result(property = "description", column = "description"),@Result(property = "users", column = "id",many = @Many(select = "com.example.mapper.UserMapper.getUsersWithDeptByRoleId"))})Role getRoleWithUsersAndDept(Long roleId);
}@Mapper 
public interface UserMapper {@Select("SELECT * "+"FROM user u " +"INNER JOIN user_role ur ON u.id = ur.user_id " +"LEFT JOIN department d ON u.dept_id = d.id " +"WHERE ur.role_id = #{roleId}")@Results({@Result(property = "id", column = "id"),@Result(property = "name", column = "name"),@Result(property = "email", column = "email"),@Result(property = "deptId", column = "dept_id"),@Result(property = "department.deptName", column = "dept_name"),@Result(property = "department.location", column = "location")})List<User> getUsersWithDeptByRoleId(Long roleId);
}

总结

MyBatis的注解方式为我们提供了灵活的联合查询解决方案。虽然在复杂查询方面可能不如XML配置那样强大,但对于大部分常见场景来说已经足够了。

http://www.lryc.cn/news/614851.html

相关文章:

  • 【洛谷题单】--分支结构(三)
  • JAVA基础-使用BIO / NIO实现聊天室功能
  • 一文详解 C++ 继承体系
  • AI_RAG
  • 本地连接跳板机
  • 10. 怎么实现深拷贝?
  • ABP VNext + Apache Kafka Exactly-Once 语义:金融级消息一致性实战
  • VSCode添加Python、Java注释技巧、模板
  • 笔试——Day33
  • java web项目入门了解
  • 微信原生小程序 Timeline 组件实现
  • 在Word和WPS文字中快速拆分、合并表格
  • JavaWeb03——javascript基础语法
  • C++-AVL树
  • 微软将于 10 月停止混合 Exchange 中的共享 EWS 访问
  • SOLi-LABS Page-3 (Stacked injections) --39-53关
  • 使用 Vuepress + GitHub Pages 搭建项目文档(2)- 使用 GitHub Actions 工作流自动部署
  • 如何解决 Vue 项目启动时出现的 “No such module: http_parser” 错误问题
  • 2G内存的服务器用宝塔安装php的fileinfo拓展时总是卡死无法安装成功的解决办法
  • 企业级web应用服务器TOMCAT入门详解
  • kettle插件-kettle MinIO插件,轻松解决文件上传到MinIO服务器
  • 解决本地连接服务器ollama的错误
  • 大语言模型提示工程与应用:大语言模型对抗性提示安全防御指南
  • LLVM编译器入门
  • Java基础-TCP通信单服务器接受多客户端
  • 关于开发语言的一些效率 从堆栈角度理解一部分c java go python
  • 软考 系统架构设计师系列知识点之杂项集萃(119)
  • 数据结构(9)——排序
  • QT第三讲- 机制、宏、类库模块
  • 数字图像处理基础——opencv库(Python)