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配置那样强大,但对于大部分常见场景来说已经足够了。