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();
}