假设有两种表,分别为用户表tb_user,用户人脸照片表tb_face。一个用户可能对应多张人脸照片。在查询用户的时候,需要将人脸照片数据一起查询出来。
数据库表结构:
表一(tb_user)
字段 | 类型 | 默认值 | 允许NULL | 主键 | 外键 | 备注 |
---|---|---|---|---|---|---|
client_id | int | NN | PK | |||
group_id | varchar(32) | NN | PK | |||
user_id | varchar(32) | NN | PK | |||
user_info | varchar(200) | |||||
create_time | datetime |
表二(tb_face)
字段 | 类型 | 默认值 | 允许NULL | 主键 | 外键 | 备注 |
---|---|---|---|---|---|---|
face_id | bigint | NN | PK | AI | ||
client_id | int | NN | ||||
group_id | varchar(32) | NN | ||||
user_id | varchar(32) | NN | ||||
face_token | varchar(32) | NN | UQ | |||
image | mediumtext | NN | ||||
create_time | datetime | NN |
tb_face表与tb_user表的关联字段为:client_id、group_id、user_id。
Java实体类
实体类一(UserEntity)
@TableName("tb_user")
public class UserEntity {
private int clientId;
private String groupId;
private String userId;
private String userInfo;
protected Date createTime;
private List<FaceEntity> faceEntityList;
// ... 省略setter/getter
}
faceEntityList 就是从tb_user表中关联出来的tb_face数据。
实体类二(FaceEntity)
@TableName("tb_face")
public class FaceEntity {
private long faceId;
private int clientId;
private String groupId;
private String userId;
private String faceToken;
private String image;
protected Date createTime;
// ... 省略setter/getter
}
实现这种一对多的关联查询有两个方式,一种是关联查询,一种是分步查询。
1、先看关联查询的MyBatis写法:
UserDao.xml
<resultMap id="userFaceResultMap" type="UserEntity">
<id column="client_id" property="clientId"/>
<id column="group_id" property="groupId"/>
<id column="user_id" property="userId"/>
<result column="user_info" property="userInfo"/>
<result column="create_time" property="createTime"/>
<collection property="faceEntityList" ofType="FaceEntity">
<id column="face_id" property="faceId"/>
<result column="client_id" property="clientId"/>
<result column="group_id" property="groupId"/>
<result column="user_id" property="userId"/>
<result column="face_token" property="faceToken"/>
<result column="image" property="image"/>
<result column="face_create_time" property="createTime"/>
</collection>
</resultMap>
<select id="queryUserFaceList" resultMap="userFaceResultMap">
SELECT u.client_id,u.group_id,u.user_id,u.user_info,u.create_time,
f.face_id,f.face_token,f.image,f.create_time AS face_create_time
FROM tb_user u LEFT JOIN tb_face f
ON(u.client_id=f.client_id AND u.group_id=f.group_id AND u.user_id=f.user_id)
WHERE u.client_id=#{clientId} AND u.group_id=#{groupId}
</select>
这种关联查询方式需要注意,t_face表查询的resultMap一定要定义一个id,并且这个id的名称在查询的列表中只能有一个,如果两个表之间id重名,必须使用别名。从SQL我们看到t_user表有create_time,t_face表也有create_time,因此给t_face表的create_time定义了一个别名叫face_create_time。
在resultMap中定义的id,可以看成是关联字段,如果查询结果出现id字段名称重复就会导致关联出来的数据与直接执行SQL时看到的结果不一样,往往只出现一条数据。
2、再看分步查询的MyBatis写法:
先在UserDao.xml中编写t_user的查询
<resultMap id="userFaceResultMap" type="UserEntity">
<id column="client_id" property="clientId"/>
<id column="group_id" property="groupId"/>
<id column="user_id" property="userId"/>
<result column="user_info" property="userInfo"/>
<result column="create_time" property="createTime"/>
<collection property="faceEntityList"
column="{clientId=client_id, groupId=group_id, userId=user_id}"
select="FaceDao.getFaceList" />
</resultMap>
<select id="queryUserFaceList" resultMap="userFaceResultMap">
SELECT u.client_id,u.group_id,u.user_id,u.user_info,u.create_time
FROM tb_user u WHERE u.client_id=#{clientId} AND u.group_id=#{groupId}
</select>
可以看到在resultMap中有一个collection指向了FaceDao.getFaceList,也就是表示会调用FaceDao.xml中的getFaceList。column指定了查询条件和别名。
FaceDao.xml
<select id="getFaceList" resultType="FaceEntity">
SELECT u.* FROM tb_face u
WHERE u.client_id=#{clientId} AND u.group_id=#{groupId} AND u.user_id=#{userId}
</select>