Mybatis入门笔记(9)——多表操作之多对多
多对多
需求:
用户和角色
一个用户可以有多个角色
一个角色可以赋予多个用户
分析:
- User表和Role表具有多对多关系,需要使用中间表,中间表中包含各自的主键,在中间表中是外键;
- 建立两个实体类:用户实体类中包含对角色的集合引用,角色实体类中包含对用户的集合引用;
- 建立两个配置文件:用户的配置文件和角色的配置文件;
- 实现功能:
- 查询用户时,同时得到用户所包含的角色信息;
- 查询角色时,同时得到角色对应的用户信息;
先建立单表查询Role表的所有信息,步骤如下:
-
往数据库中插入两张表:role表和user_role表
DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `ID` int(11) NOT NULL COMMENT '编号', `ROLE_NAME` varchar(30) default NULL COMMENT '角色名称', `ROLE_DESC` varchar(60) default NULL COMMENT '角色描述', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校'); DROP TABLE IF EXISTS `user_role`; CREATE TABLE `user_role` ( `UID` int(11) NOT NULL COMMENT '用户编号', `RID` int(11) NOT NULL COMMENT '角色编号', PRIMARY KEY (`UID`,`RID`), KEY `FK_Reference_10` (`RID`), CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`), CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `user_role`(`UID`,`RID`) values (41,1),(45,1),(41,2);
-
创建Role的实体类;
public class Role implements Serializable { private int roleId; private String roleName; private String roleDesc; public int getRoleId() { return roleId; } public void setRoleId(int roleId) { this.roleId = roleId; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } @Override public String toString() { return "Role{" + "roleId=" + roleId + ", roleName='" + roleName + '\'' + ", roleDesc='" + roleDesc + '\'' + '}'; } }
-
创建Dao接口
public interface IRoleDao { //查询所有用户 List<Role> findAll(); }
-
编写映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ben.dao.IRoleDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="roleMap" type="role"> <!--id唯一标识,type:对应的对象--> <!-- 主键字段的对应 --> <id property="roleId" column="id"></id> <!--非主键字段的对应--> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> </resultMap> <!-- 查询所有 --> <select id="findAll" resultMap="roleMap"> select * from role; </select> </mapper>
-
编写测试类
//查询用户 @Test public void testFindAll() throws IOException { List<Role> list = roleDao.findAll(); for (Role role : list) { System.out.println(role); } }
角色到用户多对多查询
-
编辑查询sql语句
select u.*,r.id as rid,r.role_name,r.role_desc from role r left outer join user_role ur on r.id = ur.rid left outer join user u on u.id = ur.uid
运行结果如下:
-
在实体类中加入多对多的关系映射
//多对多的关系映射:一个角色可以赋予多个用户 private List<User> users; public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; }
-
编写映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ben.dao.IRoleDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="roleMap" type="role"> <!--id唯一标识,type:对应的对象--> <!-- 主键字段的对应 --> <id property="roleId" column="rid"></id> <!--非主键字段的对应--> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> <collection property="users" ofType="user"> <id column="useId" property="id"></id> <result column="username" property="userName"></result> <result column="address" property="userAddress"></result> <result column="sex" property="userSex"></result> <result column="birthday" property="userBirthday"></result> </collection> </resultMap> <!-- 查询所有 --> <select id="findAll" resultMap="roleMap"> select u.*,r.id as rid,r.role_name,r.role_desc from role r left outer join user_role ur on r.id = ur.rid left outer join user u on u.id = ur.uid </select> </mapper>
-
测试类编写
//查询用户 @Test public void testFindAll() throws IOException { List<Role> list = roleDao.findAll(); for (Role role : list) { System.out.println("---每个用户的角色----"); System.out.println(role); System.out.println(role.getUsers()); } }
用户到角色的多对多查询
-
编写SQL语句
select u.*,r.id as rid,r.role_name,r.role_desc from user u left outer join user_role ur on u.id = ur.uid left outer join role r on r.id = ur.rid
如图所示:
-
在User实体类中加入多对多的关系映射;
// 配置多对多关系映射: private List<Role> roles; public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; }
-
配置映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ben.dao.IUserDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="userMap" type="uSer"> <!-- 主键字段的对应 --> <id property="userId" column="id"></id> <!--非主键字段的对应--> <result property="userName" column="username"></result> <result property="userAddress" column="address"></result> <result property="userSex" column="sex"></result> <result property="userBirthday" column="birthday"></result> <collection property="roles" ofType="role"> <id property="roleId" column="rid"></id> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> </collection> </resultMap> <!-- 查询所有 --> <select id="findAll" resultMap="userMap"> select u.*,r.id as rid,r.role_name,r.role_desc from user u left outer join user_role ur on u.id = ur.uid left outer join role r on r.id = ur.rid </select> </mapper>
-
编写测试类
//查询用户 @Test public void testFindAll() throws IOException { List<User> list = userdao.findAll(); for (User user : list) { System.out.println("----每个用户对应的角色----"); System.out.println(user); System.out.println(user.getRoles()); } }