MyBatis学习08--多表关联查询

知识点-一(多)对一

1. 需求

​ 本次案例以简单的用户和账户的模型来分析 Mybatis 多表关系。用户为 User 表,账户为Account 表。一个用户(User)可以有多个账户(Account),但是一个账户(Account)只能属于一个用户(User)。具体关系如下:
MyBatis学习08--多表关联查询
查询所有账户信息, 关联查询账户的用户名和地址
因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。

数据库的准备

CREATE TABLE t_account(
		aid INT PRIMARY KEY auto_increment,
		money DOUBLE,
		uid INT
);
ALTER TABLE t_account ADD FOREIGN KEY(uid) REFERENCES t_user(uid);

INSERT INTO `t_account` VALUES (null, '1000', '1');
INSERT INTO `t_account` VALUES (null, '2000', '1');
INSERT INTO `t_account` VALUES (null, '1000', '2');
INSERT INTO `t_account` VALUES (null, '2000', '2');
INSERT INTO `t_account` VALUES (null, '800', '3');

2. 查询语句

select * from t_account a,t_user u where a.uid=u.uid AND aid=#{aid}

3. 实现

修改Account.java
在 Account 类中加入 User类的对象作为 Account 类的一个属性。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account implements Serializable {
    private Integer aid;
    private Double money;
    private Integer uid;
    /**
     * 表示Account和User的一对一关系
     */
    private User user;
}

AccountDao.java

package com.itheima.dao;

import com.itheima.pojo.Account;

/**
 * 包名:com.itheima.dao
 *
 * @author Leevi
 * 日期2020-10-30  10:23
 */
public interface AccountDao {
    /**
     * 根据aid查询账户信息,并且连接t_user表查询该账户所属的用户信息
     * @param aid
     * @return
     */
    Account findAccountUserByAid(int aid);
}

AccountDao.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.itheima.dao.AccountDao">
    
    <resultMap id="accountUserMap" type="Account" autoMapping="true">
        <!--
            使用association标签进行一对一映射
                property属性: 要进行一对一映射的属性名
                javaType属性: 要进行一对一映射的属性类型
        -->
        <association property="user" autoMapping="true" javaType="User">
        </association>
    </resultMap>
    <select id="findAccountUserByAid" parameterType="int" resultMap="accountUserMap">
        select
        *
        from
        t_account a,t_user u
        where
        a.uid=u.uid
        AND
        a.aid=#{aid}
    </select>
</mapper>

2.一对多

查询所有用户信息及用户关联的账户信息。
分析: 用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,想到了左外连接查询比较合适。

select * from t_user u,t_account a where a.uid=u.uid AND u.uid=#{uid}

2.1实现

Account.java

public class Account {
    private Integer aid;
    private Integer uid;
    private Double money;
}

User.java
​ 为了能够让查询的 User 信息中,带有他的个人多个账户信息,我们就需要在 User 类中添加一个集合,
用于存放他的多个账户信息,这样他们之间的关联关系就保存了。

public class User implements Serializable{
    private int uid;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    //表达关系:1个用户对应多个账户
    private List<Account> accountList;
}

UserDao.java

package com.itheima.dao;

import com.itheima.pojo.User;

/**
 * 包名:com.itheima.dao
 * @author Leevi
 * 日期2020-10-29  12:22
 *
 */
public interface UserDao {
    /**
     * 根据用户的uid查询到一个用户信息,并且连接账号表查询该用户的所有账号
     * @param uid
     * @return
     */
    User findUserAccountListByUid(int uid);
}

UserDao.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.itheima.dao.UserDao">
    <resultMap id="userAccountListMap" type="User">
        <id column="uid" property="uid"/>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>
        <!--
            对accountList属性进行一对多映射,使用collection标签
                property属性: 要进行一对多映射的属性名
                ofType属性(可以不写): 要进行一对多映射的属性类型
        -->
        <collection property="accountList" autoMapping="true" ofType="Account">
        </collection>
    </resultMap>

    <select id="findUserAccountListByUid" resultMap="userAccountListMap" parameterType="int">
        SELECT
        *
        FROM
        t_user u,t_account a
        WHERE
        a.uid=u.uid
        AND
        u.uid=#{uid}
    </select>
</mapper>

多对多(可以看成俩一对多)

3.通过前面的学习,使用 Mybatis 实现一对多关系的维护。多对多关系其实看成是双向的一对多关系。用户与角色的关系模型就是典型的多对多关系.

MyBatis学习08--多表关联查询

需求:实现查询所有角色对象并且加载它所分配的用户信息。
建表语句

CREATE TABLE t_role(
	rid INT PRIMARY KEY AUTO_INCREMENT,
	rName varchar(40),
	rDesc varchar(40)
);
INSERT INTO `t_role` VALUES (null, '校长', '负责学校管理工作');
INSERT INTO `t_role` VALUES (null, '副校长', '协助校长负责学校管理');
INSERT INTO `t_role` VALUES (null, '班主任', '负责班级管理工作');
INSERT INTO `t_role` VALUES (null, '教务处主任', '负责教学管理');
INSERT INTO `t_role` VALUES (null, '班主任组长', '负责班主任小组管理');


-- 中间表(关联表)
CREATE TABLE user_role(
	uid INT,
	rid INT
);

ALTER TABLE  user_role ADD FOREIGN KEY(uid) REFERENCES t_user(uid);
ALTER TABLE  user_role ADD FOREIGN KEY(rid) REFERENCES t_role(rid);

INSERT INTO `user_role` VALUES ('1', '1');
INSERT INTO `user_role` VALUES ('3', '3');
INSERT INTO `user_role` VALUES ('2', '3');
INSERT INTO `user_role` VALUES ('2', '5');
INSERT INTO `user_role` VALUES ('3', '4');

3.1分析

查询角色需要用到 Role 表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE 表)才能关联到用户信息。
下面是实现的 SQL 语句:

select * from t_user u,t_role r,user_role ur where ur.uid=u.uid and ur.rid=r.rid AND u.uid=#{uid}

3.2实现

User.java

package com.itheima.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 包名:com.itheima.pojo
 *
 * @author Leevi
 * 日期2020-07-29  09:03
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private Integer uid;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
    /**
     * user和role的一对多关系
     */
    private List<Role> roleList;
}

Role.java

public class Role {
    private Integer rid;
    private String rName;
    private String rDesc;	
}

UserDao.java

package com.itheima.dao;

import com.itheima.pojo.User;

/**
 * 包名:com.itheima.dao
 *
 * @author Leevi
 * 日期2020-10-30  11:31
 */
public interface UserDao {
    User findUserRoleListByUid(int uid);
}

UserDao.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.itheima.dao.UserDao">
    <resultMap id="userRoleListMap" type="User">
        <id column="uid" property="uid"/>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>
        <collection property="roleList" autoMapping="true" ofType="Role"></collection>
    </resultMap>
    <select id="findUserRoleListByUid" parameterType="int" resultMap="userRoleListMap">
        SELECT
        *
        FROM
        t_user u,t_role r,user_role ur
        WHERE
        ur.uid=u.uid
        AND
        ur.rid=r.rid
        AND
        u.uid=#{uid}
    </select>
</mapper>

小结:

1.以哪张表作为主体查询,那么就将查询到的结果封装到哪张表对应的POJO对象中
2.如果表的关系是一对一,那么就在一个POJO中添加另外一个POJO的对象属性
3.如果表的关系是一对多,那么就在一个POJO中添加另外一个POJO的集合属性
4.使用association标签可以进行一对一的映射
5.使用collection标签可以进行一对多的映射

上一篇:SpringBoot--""Required request part 'file' is not present""


下一篇:RequestParam注解的使用