mybatis一对多 多对多 多对一

mybatis一对多 多对多 多对一 的相关操作

统一声明 :联表查询这里不使用外键,使用Java代码实现表与表之间的关联

1.多对一的额外 SQL 查询(额外发送SQL的方式)

在这里插入图片描述
在这里插入图片描述
数据库代码链接:https://pan.baidu.com/s/1vmUyeX5CCNjOt5Lu0pSxhw

多对一,是在"多"的一方关联"一"的一方。显然一个用户对应的只有一个身份,而一个身份可以对应多个用户。所以我们需要在用户实体类中关联角色实体类

package cn.wolfcode.mybatis.domain;

import java.math.BigDecimal;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class User {
	private Long id;
	private String username;
	private String password;
	private Integer age;
	private BigDecimal salary;
	//关联角色表
	private Role role;
}

package cn.wolfcode.mybatis.mapper;

import cn.wolfcode.mybatis.domain.Role;

/**
 * 
 * @author 红烛
 *
 */


public interface RoleMapper {
	/**
	 * 通过id查寻角色信息
	 * @param id
	 * @return
	 */
	 Role get(Long id);
}

查询操作需要两条sql
1>select id,username,password,age,salary,roleId from user where id=#{id}
2>select id,role from role where id=#{id}
或者使用连表查询
select u.id, u.username,u.password,u.age,u.salary,r.id ,r.role from user u join role r on u.roleId=r.id
where u.id=#{id}

首先我们使用第一种方法
解决办法:在执行select id,username,password,age,salary,roleId from user where id=#{id}的时候让mybatis给我们额外发送另一条SQL。
我们需要在UserMapper.xml这样配置:

    <resultMap type="User" id="BaseMap">
    		<id property="id" column="id"/>
    		<result property="username" column="username"/>
    		<result property="password" column="password"/>
    		<result property="age" column="age"/>
    		<result property="salary" column="salary"/>
    		//下面这行是关 ,该属性不是集合类型;
    		// role是User表的字段名(可以回去看一下),是你关联的的对象;
    		//column 列的值传递额外SQL的参数值
    		//select指的是发送的额外的SQL语句,cn.wolfcode.mybatis.mapper.RoleMapper.get指cn.wolfcode.mybatis.mapper.RoleMapper文件中id为get的那条sql
    		<association property="role" column="roleId" select="cn.wolfcode.mybatis.mapper.RoleMapper.get"/>
   </resultMap>

着重理解一下column的传值:在这里是通过id查询用户信息时同时将role表中所关联的对应信息查出,
当执行select id,username,password,age,salary,roleId from user where id=#{id}这条SQL时,需将roleId的值传到需要发送的sql中,也就是select id,role from role where id=#{id},用于将相关联的信息查出,因为user表中roleId关联role表的id(虽然没有用外键,这是我们通过代码关联的,查询时使满足两个id值相同)。发送额外sql所需传递的值的列名就是column中的内容。
一切准备就绪,就让我们测试一下吧
mapper接口中方法

 Role get(Long id);

 User get(Long id);

@Test
	public void testGet(){
		SqlSession session=MybatisUtil.getSession();
		UserMapper userMapper=session.getMapper(UserMapper.class);
		User user=userMapper.get(1L);
		System.out.println(user);
		session.commit();
		session.close();
	}

结果如下:可以看出发送了两条sql

DEBUG [main] - ==>  Preparing: select id,username,password,age,salary,roleId from user where id=? 
DEBUG [main] - ==> Parameters: 1(Long)
DEBUG [main] - ====>  Preparing: select id,role from role where id=? 
DEBUG [main] - ====> Parameters: 1(Long)
DEBUG [main] - <====      Total: 1
DEBUG [main] - <==      Total: 1
User(id=1, username=白玉亭, password=123456, age=19, salary=20000.00, role=Role(id=1, role=经理))

先在我们来看第二种方法,联表查询
查询的SQL为
select u.id, u.username,u.password,u.age,u.salary,r.id ,r.role from user u join role r on u.roleId=r.id
where u.id=#{id}
其他的都不需要变,需要改的是UserMapper.xml中的association 部分。注意:如果你两个表中有相同字段的列名,需要给取别名区分一下。

<association property="role">
		<result property="id" column="id"/>
		<result property="role" column="role"/>
	</association>

ps:若有设置别名,请参考以下写法:

<resultMap id="baseResultMap" type="Employee">
	<id column="id" property="id"/>
	<result column="name" property="name"/>
	<result property="d_id" column="dept.id"/>
	<result property="d_name" column="dept.name"/>
</resultMap>
<resultMap id="baseResultMap" type="Employee">
	<id column="id" property="id"/>
	<result column="name" property="id"/>
	<association property="dept" javaType="Department">
		<result property="d_id" column="id"/>
		<result property="d_name" column="name"/>
	</association>
</resultMap>
<resultMap id="baseResultMap" type="Employee">
	<id column="id" property="id"/>
	<result column="name" property="id"/>
	<association property="dept" javaType="Department" columnPrefix="d_">
		<result property="id" column="id"/>
		<result property="name" column="name"/>
	</association>
</resultMap>

三种写法一样,但显然第三种写法最优。

2.多对一的保存操作

mapper接口方法

 <!--UserMapper.java-->
 void save(Role role);
 <!--RoleMapper.java-->
 void save(User user);

xml

 <!--UserMapper.xml-->
 <insert id="save" useGeneratedKeys="true" keyProperty="id">
    	  insert into user(id,username,password,age,salary,roleId) values(#{id},#{username},
    	  #{password},#{age},#{salary},#{roleId})
 </insert>
 <!--RoleMapper.xml-->
 <insert id="save" useGeneratedKeys="true" keyProperty="id">
          insert into role(role) values #{role}
 </insert>

//需求:保存一个角色身份和两个用户,且这两个员工都是同样的角色身份
	@Test
	public void testSave(){
		SqlSession session=MybatisUtil.getSession();
		UserMapper userMapper=session.getMapper(UserMapper.class);
		RoleMapper roleMapper=session.getMapper(RoleMapper.class);
		//先保存角色身份信息
		Role role =new Role();
		role.setRole("后勤");
		roleMapper.save(role);
		
	//后保存user对象
	User user=new User();
	user.setUsername("小白");
	user.setAge(18);
	user.setPassword("123456");
	user.setSalary(new BigDecimal("18000"));
	user.setRole(role);
	userMapper.save(user);
	
	User user1=new User();
	user1.setUsername("小白");
	user1.setAge(18);
	user1.setPassword("123456");
	user1.setSalary(new BigDecimal("18000"));
	user1.setRole(role);
	userMapper.save(user1);
	
	session.commit();
	session.close();
}

3.一对多的额外 SQL 查询

一对多是在一的地方关联多的实体类

<!--Role.java-->
@Getter
@Setter
@ToString
public class Role {
	private Long id;
	private String role;
	private List<User> users =new ArrayList<User>();
}

<!--User.java-->
@Getter
@Setter
@ToString
public class User {
	private Long id;
	private String username;
	private String password;
	private Integer age;
	private BigDecimal salary;
	private Long roleId;
}

mapper

<!--RoleMapper.xml-->
List<User> listAll(Long id);
<!--UserMapper.xml-->
List<User> listAll(Long roleId);

Mapper.xml

<!--RoleMapper.xml-->
    <resultMap type="Role" id="BaseMap">
    		<id property="id" column="id"/>
    		<result property="role" column="role"/>
    		<collection property="users" column="id" select="cn.wolfcode.mybatis.mapper.UserMapper.listAll"/>
    	</resultMap>
    	
    	<select id="listAll" resultMap="BaseMap">
    		select id,role from role where id=#{id}
    	</select>

<sql id="Base_Cloumn_List">
		id,username,password,age,salary,roleId
	</sql>

<!--UserMapper.xml-->
    	<select id="listAll" resultType="User">
    		select
    		<include refid="Base_Cloumn_List"/>
    		from user
    		where roleId=#{roleId}
    	</select>

test

@Test
public void testListAll() throws Exception {
	SqlSession session=MybatisUtil.getSession();
	RoleMapper roleMapper=session.getMapper(RoleMapper.class);
	List<User> users=roleMapper.listAll(1L);
	System.out.println(users);
	session.commit();
	session.close();
}

4.多对多的保存操作

在这里插入图片描述
对象关系维护
这里是单向的,关联属性在 user方,关系则由其维护。

实体类设计

<!--Role.java-->
    @Getter
    @Setter
    @ToString
    public class Role {
    	private Long id;
    	private String role;
    }

<!--User.jave-->
@Getter
@Setter
@ToString
public class User {
	private Long id;
	private String username;
	private String password;
	private Integer age;
	private BigDecimal salary;
	private Long roleId;
	//在user方维护关系
	private List<Role> roles;
}

中间表 user_role 表
在这里插入图片描述
代码执行流程如下,多余的就不说了:
在这里插入图片描述

5.多对多的删除和查询操作

删除操作

核心代码

/**
 * 删除用户表中的用户
 */
@Delete(value = { "delete from user where id=#{id}" })
void delete();

/**
 * 在中间表中删除已删除用户相关的角色信息
 * @param id
 */
@Delete(value = { "delete from user_role where user_id=#{user_id}" })
void deleteRelationWithRole(@Param("user_id")  Long id);

test

@Test
	public void testDelete(){
		SqlSession session=MybatisUtil.getSession();
		UserMapper userMapper=session.getMapper(UserMapper.class);
		userMapper.delete(49L);
		userMapper.deleteRelationWithRole(49L);
		session.commit();
		session.close();
	}

查询操作

使用额外发送SQL的方式
需要的SQL如下:
//第一条发送的SQL
select * from user where id=#{id}
//额外发送的SQL 先从中间表查出role 的id集合 ,在根据集合查出role表的数据
select id,role from role where id in(select role_id from user_role where user_id=#{user_id})

mapper

<!--UserMapper.java-->
    User select(Long id);
 <!--RoleMapper.java-->
    List<Role> getRoleByUser(@Param("user_id")Long id);

mapper.xml
摘录相关的代码

   <!--UserMapper.xml-->
        	<resultMap id="BaseMap" type="User">
        		<id property="id" column="id"/>
        		<result property="username" column="username"/>
        		<result property="password" column="password"/>
        		<result property="age" column="age"/>
        		<result property="salary" column="salary"/>
        		<result property="roleId" column="roleId"/>
        		<collection property="roles" column="id" select="cn.wolfcode.mybatis.mapper.RoleMapper.getRoleByUser" />
        	</resultMap>
        	
    	    <select id="select" resultMap="BaseMap">
    	    		select * from user where id=#{id}
    	    </select>

<!--RoleMapper.xml-->
<select id="getRoleByUser" resultType="Role">
		select id,role from role where id in(select role_id from user_role where user_id=#{user_id})
</select>

test测试代码

@Test
public void testSelect(){
	SqlSession session=MybatisUtil.getSession();
	UserMapper userMapper=session.getMapper(UserMapper.class);
	User user=userMapper.select(50L);
	System.out.println(user);
	session.commit();
	session.close();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值