MyBatis学习08--多表关联查询
知识点-一(多)对一
1. 需求
本次案例以简单的用户和账户的模型来分析 Mybatis 多表关系。用户为 User 表,账户为Account 表。一个用户(User)可以有多个账户(Account),但是一个账户(Account)只能属于一个用户(User)。具体关系如下:
查询所有账户信息, 关联查询账户的用户名和地址。
因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。
数据库的准备
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 实现一对多关系的维护。多对多关系其实看成是双向的一对多关系。用户与角色的关系模型就是典型的多对多关系.
需求:实现查询所有角色对象并且加载它所分配的用户信息。
建表语句
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标签可以进行一对多的映射