MyBatis的多对多映射(十)

本文介绍MyBatis的多对多关联映射,将其处理成双向一对多关联。详细阐述角色到员工、员工到角色的一对多查询,以及嵌套结果查询。还引入UserRole实体处理特殊字段。查询时可能只显示一条数据,原因与数据是否相同有关,MyBatis会将相同实例化数据当成一个对象。

年轻的时候,遇见了一个人,便以为余生再没有江湖,后来,才懂,她才是江湖的起源。

上一章简单介绍了MyBatis的一对多映射(九),如果没有看过,请观看上一章

一. Mybatis的多对多关联映射

多对多的关系在数据库中是很常见的,但是在业务代码中常常处理成 双向的一对多的关联。 可以与Hibernate的多对多对照来看:
Hibernte的多对多映射(十二)

创建User表:
有图片

创建Role 角色表:

在这里插入图片描述

创建User_role 表

有图片

相应的实体类:

User.java

package com.yjl.pojo;

import java.util.List;

/**
 @author:yuejl
 @date: 2019年6月15日 上午11:11:02
 @Description Mybatis 使用的基本类 User
*/
public class User {
	/**
	 * @param id id编号,自增
	 * @param name 姓名
	 * @param age 年龄
	 * @param sex 性别
	 * @param description 描述
	 */
	private Integer id;
	private String name;
	private Integer age;
	private String sex;
	private String description;
	//引入角色的多个对象集合。。
	private List<Role> roles;
	public User(){
		
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public List<Role> getRoles() {
		return roles;
	}
	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", description=" + description
				+ "]";
	}
}

Role.java

package com.yjl.pojo;

import java.util.List;

/**
 @author:两个蝴蝶飞
 @date: 2019年3月2日 下午6:18:51
 @Description 角色组
*/
public class Role {
	/**
	 * @param id 角色编号
	 * @param name 用户的名称
	 */
	private Integer id;
	private String name;
	public Role() {
	}
	public Role(String name) {
		this.name = name;
	}
	/**
	 * @param users 用户   是一对多的关系
	 */
	private List<User> users;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<User> getUsers() {
		return users;
	}
	public void setUsers(List<User> users) {
		this.users = users;
	}
	@Override
	public String toString() {
		return "Role [id=" + id + ", name=" + name + "]";
	}
}

二. 角色到员工的一对多查询(select 形式)

RoleMapper.java 中接口:

public Role findByIdWithSelect(int id);

UserMapper.java 中接口:

public List<User> findUserByRoleId(@Param(value="roleId") int roleId);

RoleMapper.xml sql语句:

<!--角色查询员工的一对多-->
<resultMap type="role" id="roleResultMapWithSelect">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<collection property="users" ofType="user" column="id"
		select="com.yjl.mapper.UserMapper.findUserByRoleId"></collection>
	</resultMap>

<select id="findByIdWithSelect" parameterType="int" resultMap="roleResultMapWithSelect">
		select * from role t where t.id=#{id}
</select>

UserMapper.xml 中sql语句

<resultMap type="user" id="userResultMap">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
	</resultMap>
<select id="findUserByRoleId" parameterType="int" resultMap="userResultMap">
		select u.* from user_role t,user u where t.userId=u.id and t.roleId=#{roleId}
	</select>

测试方法:

@Test
	public void findByIdWithSelectTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		RoleMapper roleMapper=sqlSession.getMapper(RoleMapper.class);
		//具有超级管理员角色的用户
		Role role=roleMapper.findByIdWithSelect(1);
		System.out.println(role);
		List<User> userList=role.getUsers();
		userList.forEach(n ->System.out.println(n));
	}

有图片。

三. 员工到角色的一对多的嵌套select 查询

UserMapper.java 接口:

public User getByIdWithSelect(int id);

RoleMapper.java 接口:

public List<Role> findRoleByUserId(@Param(value="userId") int userId);

UserMapper.xml sql语句:

<resultMap type="user" id="userResultMapWithSelect">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
		<collection property="roles" ofType="role" column="id"
		select="com.yjl.mapper.RoleMapper.findRoleByUserId"></collection>
	</resultMap>
<!-- 嵌套select -->
	<select id="getByIdWithSelect" parameterType="int" resultMap="userResultMapWithSelect">
		select * from user where id=#{id}
	</select>

RoleMapper.xml 中sql语句:

<resultMap type="role" id="roleResultMap">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
	</resultMap>
<select id="findRoleByUserId" parameterType="int" resultMap="roleResultMap">
		select r.* from user_role t,role r where t.roleId=r.id and t.userId=#{userId}
	</select>

测试方法:

@Test
	public void getByIdWithSelectTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		//查询该员工所具有的角色
		User user=userMapper.getByIdWithSelect(1);
		System.out.println(user);
		List<Role> roleList=user.getRoles();
		roleList.forEach(n ->System.out.println(n));
	}

有图片。

四. user 到role 的嵌套结果 查询

UserMapper.java 接口

public User getByIdWithResult(int id);

UserMapper.xml sql

<resultMap type="user" id="userResultMapWithResult">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
		<collection property="roles" javaType="ArrayList" ofType="role">
			<id property="id" column="rid"/>
			<result property="name" column="rname"/>
		</collection>
	</resultMap>
<!-- 用具体的语句,而不是 * 这样的。 -->
	<select id="getByIdWithResult" parameterType="int" resultMap="userResultMapWithResult">
		select u.*,r.id as rId,r.name as rname from user u,role r ,user_role ur where u.id=ur.userId and r.id=ur.roleId
		and ur.userId=#{id}
	</select>

测试方法:

@Test
	public void getByIdWithResultTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		User user=userMapper.getByIdWithResult(1);
		System.out.println(user);
		List<Role> roleList=user.getRoles();
		roleList.forEach(n ->System.out.println(n));
	}

有图片。

可以发现,多对多实际上就是两个一对多的关系。 完全按照一对多的模式进行做。

但是一般,员工和角色表时不但会有userId,roleId, 还常常会有 created_by,created_time, 即创建人和创建时间等字段,这个时候就不能用上面的方式, 需要引入另外一个实体 UserRole 实体, 转换成两个一对多的关系, User与UserRole 是一对多的关系,Role 与UserRole 也是一对多的关系。

五. UserRolee 实体类的两个一对多关联

User 表 和Role 表,保持不变。

对UserRole 表,添加两个字段。

有图片。

那么User.java 实体类就改变成了:

package com.yjl.pojo;

import java.util.List;

/**
 @author:yuejl
 @date: 2019年6月15日 上午11:11:02
 @Description Mybatis 使用的基本类 User
*/
public class User {
	/**
	 * @param id id编号,自增
	 * @param name 姓名
	 * @param age 年龄
	 * @param sex 性别
	 * @param description 描述
	 */
	private Integer id;
	private String name;
	private Integer age;
	private String sex;
	private String description;
	//引入员工角色的多个对象集合。。
	private List<UserRole> userRole;
	public User(){
		
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public List<UserRole> getUserRole() {
		return userRole;
	}
	public void setUserRole(List<UserRole> userRole) {
		this.userRole = userRole;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + ", description=" + description
				+ "]";
	}
}

其中的 Role.java 变成了:

package com.yjl.pojo;

import java.util.List;

/**
 @author:两个蝴蝶飞
 @date: 2019年3月2日 下午6:18:51
 @Description 角色组
*/
public class Role {
	/**
	 * @param id 角色编号
	 * @param name 用户的名称
	 */
	private Integer id;
	private String name;
	public Role() {
	}
	public Role(String name) {
		this.name = name;
	}
	/**
	 * @param userRole 用户角色实体   是一对多的关系
	 */
	private List<UserRole> userRole;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<UserRole> getUserRole() {
		return userRole;
	}
	public void setUserRole(List<UserRole> userRole) {
		this.userRole = userRole;
	}
	@Override
	public String toString() {
		return "Role [id=" + id + ", name=" + name + "]";
	}
}


新增加一个UserRole.java 类:

package com.yjl.pojo;

import java.util.Date;

/**
@atuhor:yuejl
@Description: 类描述
*/
public class UserRole {
	private User user;
	private Role role;
	private String created_by;
	private Date created_date;
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	public Role getRole() {
		return role;
	}
	public void setRole(Role role) {
		this.role = role;
	}
	public String getCreated_by() {
		return created_by;
	}
	public void setCreated_by(String created_by) {
		this.created_by = created_by;
	}
	public Date getCreated_date() {
		return created_date;
	}
	public void setCreated_date(Date created_date) {
		this.created_date = created_date;
	}
	@Override
	public String toString() {
		return "UserRole [user=" + user + ", role=" + role + ", created_by=" + created_by + ", created_date="
				+ created_date.toLocaleString() + "]";
	}
}

六. 员工去查询角色

UserMapper.java 的接口:

public User getUserRoleById(int id);

UserMapper.xml sql语句:

<resultMap type="user" id="userResultMapWithUserRole">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
		<!--引入集合为userRole的集合-->
		<collection property="userRole" javaType="ArrayList" ofType="userRole"
		column="id" select="com.yjl.mapper.UserRoleMapper.findByUserId">
		</collection>
	</resultMap>
	
	<select id="getUserRoleById" parameterType="int" resultMap="userResultMapWithUserRole">
		select * from user where id=#{id}
	</select>

UserRoleMapper.java 的接口为:

package com.yjl.mapper;

import org.apache.ibatis.annotations.Param;

import com.yjl.pojo.UserRole;

/**
@atuhor:yuejl
@Description: 类描述
*/
public interface UserRoleMapper {
	public UserRole findByUserId(@Param(value="userId") int userId);
}

UserRoleMapper.xml 文件为:

<?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.yjl.mapper.UserRoleMapper">
	<resultMap type="userRole" id="userRoleMap">
		<result property="created_by" column="created_by" javaType="string"/>
		<result property="created_date" column="created_date" javaType="date"/>
		<!-- 关联一下,相应的角色信息,为一对一的形式 -->
		<association property="role" javaType="role" column="roleId"
		select="com.yjl.mapper.RoleMapper.findById"></association>
	</resultMap>
	
	<select id="findByUserId" parameterType="int" resultMap="userRoleMap">
		select t.* from user_role t where t.userId=#{userId}
	</select>
</mapper>

RoleMapper.java 的接口为:

public Role findById(int id);

RoleMapper.xml 的sql语句为:

<resultMap type="role" id="roleResultMap">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
</resultMap>

<select id="findById" parameterType="int" resultMap="roleResultMap">
		select * from role t where t.id=#{id}
	</select>

测试方法:

@Test
	public void getUserRoleByIdTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		//查询该员工所具有的角色
		User user=userMapper.getUserRoleById(1);
		List<UserRole> roleList=user.getUserRole();
		System.out.println(user);
		for (UserRole userRole : roleList) {
			System.out.println("输出创建人:"+userRole.getCreated_by());
			System.out.println("输出创建日期:"+userRole.getCreated_date());
			Role role=userRole.getRole();
			System.out.println(role);
		}
	}

有图片。

这是员工找角色的,也可以角色去找员工。 与上面的思路差不多,就不讲解了。 当然,也有对应的result 的形式。

UserMapper.java 接口:

public User getUserRoleByIdWithResult(int id);

UserMapper.xml sql语句:

<resultMap type="user" id="userResultMapWithUserRoleResult">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="age"/>
		<result property="description" column="description"/>
		<collection property="userRole" ofType="userRole" javaType="arrayList">
			<result property="created_by" column="created_by" javaType="string"/>
			<result property="created_date" column="created_date" javaType="date"/>
			<!-- 对角色的一对一 -->
			<association property="role" javaType="role">
				<id property="id" column="rId" javaType="int"/>
				<result property="name" column="rName" javaType="string"/>
			</association>
		</collection>
	</resultMap>
<select id="getUserRoleByIdWithResult" parameterType="int" resultMap="userResultMapWithUserRoleResult">
		select u.id as id,u.name as name,u.sex as sex,u.age as age,u.description as description,
		ur.created_by as created_by,ur.created_date as created_date,
		r.id as rId,r.name as rName,
		ur.userId as userId,ur.roleId as roleId from user u,role r,user_role ur where u.id=ur.userId and r.id=ur.roleId
		and u.id=#{id}
	</select>

测试方法:

@Test
	public void getUserRoleByIdWithResultTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		//查询该员工所具有的角色
		User user=userMapper.getUserRoleByIdWithResult(1);
		List<UserRole> roleList=user.getUserRole();
		System.out.println(user);
		System.out.println("长度是:"+roleList.size());
		for (UserRole userRole : roleList) {
			System.out.println("输出创建人:"+userRole.getCreated_by());
			System.out.println("输出创建日期:"+userRole.getCreated_date());
			Role role=userRole.getRole();
			System.out.println(role);
		}
	}

查询的时候,会发现只查询出一条数据。

有图片。

显示的是查询出3条,为什么只显示一条呢? 查了很多资料,最后发现可能跟数据有关。 user 表中的数据是一样的,给处理成了一条,那么 userrole 表中的数据也是一样的,也可以被处理成了一条。 故改变userrole 表中的数据。

有图片

这个时候,运行为:

有图片。

将userrole 中的数据再次改变,使其中有相同的。

有图片,

再次运行为:

有图片。

故可知,与数据是否相同有很大的关系。 如果实例化的数据都一样,MyBatis会将其当成一个对象,不会再重新初始化。

谢谢!!!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两个蝴蝶飞

你的鼓励,是老蝴蝶更努力写作的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值