目录
一、需求
查询某个用户的详细信息,除了 用户的基本信息 外,还包括 用户所在部门 以及 用户拥有的角色
二、分析
用户与部门:
1、一个用户 只能属于 一个部门, 一个部门 有多个 用户,所以用户与部门关系是 一 对 多
2、通过 用户查询部门,只需要 多的那边 记住 一,所以使用 一 对 多单向数据
用户与角色:
1、一个用户 有多个角色,一个角色可以分配 给多个用户, 所以用户与角色的关系是 多对多
2、通过用户查询角色
三、设计
实体设计
@Data
public class User {
private Integer id;
private String userName;
private String password;
private Date birthday;
private Dept dept;
private List<Role> roles;
}
@Data
public class Role {
private Integer id;
private String name;
private String comment;
}
@Data
public class Dept {
private Integer id;
private String name;
}
数据库表设计
CREATE TABLE `dept` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`comment` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(20) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`dept_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
表数据
INSERT INTO `dept` (`id`,`name`) VALUES (1, '研发部'),(2, '销售部'),(3, '售后部');
INSERT INTO `role` (`id`,`name`,`comment`) VALUES (1, '总经理', '总管大局'),(2, '销售经理', '负责销售'),(3, '部长', '管理部门角色');
INSERT INTO `user` (`id`,`user_name`,`password`,`birthday`,`dept_id`) VALUES (1, '张三丰', 'aaabbb', '2019-11-12', 1),(2, 'tom', '66888999', '2019-11-10', 2),(3, 'kitty', 'aaaabbb', '2018-08-12', 3);
INSERT INTO `user_role` (`id`,`user_id`,`role_id`) VALUES (1, 1, 1),(2, 1, 3),(3, 2, 1),(4, 2, 2);
四、Mapper层
接口:
public interface UserMapper {
User selectUserById(Integer id);
}
mapper映射描述文件:
<resultMap id="user" type="com.lcy.pojo.User">
<result property="id" column="u_id"/>
<result property="userName" column="u_user_name"/>
<result property="password" column="u_password"/>
<result property="birthday" column="u_birthday" javaType="java.util.Date"/>
<association property="dept" javaType="Dept">
<id property="id" column="d_id"/>
<result property="name" column="d_name" />
</association>
<collection property="roles" ofType="Role">
<id property="id" column="r_id"/>
<result property="name" column="r_name" />
<result property="comment" column="r_comment" />
</collection>
</resultMap>
<!--select * from user where id = #{id}-->
<select id="selectUserById" resultMap="user">
SELECT
u.id AS u_id,
u.user_name AS u_user_name,
u.`password` AS u_password,
u.birthday AS u_birthday,
d.id AS d_id,
d.`name` AS d_name,
r.id AS r_id,
r.`name` AS r_name,
r.COMMENT AS r_comment
FROM
`user` u
LEFT JOIN dept d ON u.dept_id = d.id
LEFT JOIN user_role ur ON u.id = ur.user_id
LEFT JOIN role r ON ur.role_id = r.id
where u.id = #{id}
</select>
五、测试代码
UserMapper mapper;
SqlSession session;
@Before
public void init() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
session = sqlSessionFactory.openSession();
mapper = session.getMapper(UserMapper.class);
}
@After
public void destory() {
session.commit();
session.close();
}
@Test
public void selectUserById() {
User user = mapper.selectUserById(2);
System.out.println(user);
}
六、思考
新增需求:
在之前是通过用户来查询部门,那么是不是也可以查询 该用户所在部门的所有用户?
即:在部门类中添加 List<User> user; 属性, 首先通过 用户 ID, 查询到用户所在的部门, 然后在获取该部门下的所有用户?
伪代码:
mapper.selectUserById(1).getDept().getUsers() // 获取用户 id为1的所有同事
分析:
这个问题, 我之前在学 hibernate的时候也遇到过, 这里做一下简单描述
类设计:
User类中 : 有Dept属性
Dept类中: 有User集合
那么我们在 使用 user.getDept()获取部门, 但如果做了双向数据绑定, 那么获取到的部门中由于含有User集合, 然后Hibernate又会去查询User, 查询到 User,但 User中又有 Dept,这样 会造成死循环!!!
总结:
无论是一对一 或是 一对多, 都不要做双向数据绑定, 否则会造成查询中的死循环问题!!!