创建两张表格? ?player 和team??
?player表
CREATE TABLE `player` (
`playerId` int NOT NULL,
`playerName` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`playerNum` int DEFAULT NULL,
`teamId` int DEFAULT NULL,
PRIMARY KEY (`playerId`),
KEY `teamId` (`teamId`),
CONSTRAINT `player_ibfk_1` FOREIGN KEY (`teamId`) REFERENCES `team` (`teamId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
team表
CREATE TABLE `team` (
`teamId` int NOT NULL AUTO_INCREMENT COMMENT '球队ID',
`teamName` varchar(50) DEFAULT NULL COMMENT '球队名称',
`location` varchar(50) DEFAULT NULL COMMENT '球队位置',
`createTime` date DEFAULT NULL COMMENT '球队建立时间',
PRIMARY KEY (`teamId`)
) ENGINE=InnoDB AUTO_INCREMENT=1013 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
插入数据如下
引出问题,mybatis如何进行多表连接查询
比如根据player表的teamId查询出所有球员的信息,在此情况下如何获取球员对于的球队信息?
1 对一关系的映射
实体类
public class Player {
private Integer playerId;
private String playerName;
private Integer playerNum;
private Integer teamId;
//多对一的体现:多方持有一方的对象 要有get方法
private Team team1;//关联对象--多个球员可以属于同一个球队;
private Team team2;//关联对象--多个球员可以属于同一个球队;
private Team team3;//关联对象--多个球员可以属于同一个球队;
//省略set get 和toString方法
}
mapper接口
public interface PlayerMapper {
List<Player> queryById1(int playerId);
List<Player> queryById2(int playerId);
List<Player> queryById3(int playerId);
}
对一映射方式1:通过关联对象打点调用属性的方式
??要求:两表的连接查询
<select id="queryById1" resultMap="JoinTeamResult1">
select * from player p inner join team t on p.teamId=t.teamId
where t.teamId=#{id}
</select>
<resultMap id="baseResultMap" type="com.kkb.pojo.Player">
<id column="playerId" property="playerId"></id>
<result column="playerName" property="playerName"></result>
<result column="playerNum" property="playerNum"></result>
<result column="teamId" property="teamId"></result>
</resultMap>
<!-- 方式1:通过关联对象打点调用属性的方式
要求:连接查询
如果连接查询,一般单独定义resultMap
extends="表示继承的其他的resultMap的id"
-->
<resultMap id="JoinTeamResult1" type="com.kkb.pojo.Player" extends="baseResultMap">
<id column="teamId" property="team1.teamId"></id>
<result column="teamName" property="team1.teamName"></result>
<result column="location" property="team1.location"></result>
<result column="teamName" property="team1.teamName"></result>
<result column="createTime" property="team1.createTime"></result>
</resultMap>
测试类
package com.kkb.test;
import com.kkb.mapper.PlayerMapper;
import com.kkb.pojo.Player;
import com.kkb.utils.MybatisUtil;
import org.junit.Test;
import java.util.List;
public class PlayerTest {
private PlayerMapper playerMapper = MybatisUtil.getSqlSession().getMapper(PlayerMapper.class);
@Test
public void test01(){
List<Player> players = playerMapper.queryById1(1005);
for (Player player : players) {
System.out.println(player);
}
}
@Test
public void test02(){
Player player = playerMapper.queryById2(1005);
for (Player player : players) {
System.out.println(player);
}
}
@Test
public void test03(){
Player player = playerMapper.queryById3(1005);
for (Player player : players) {
System.out.println(player);
}
}
}
?对一映射方式2:直接引用关联对象的Mapper映射
要求:
1、两表的连接查询 2、关联对象中已经存在被引用的resultMap
<select id="queryById2" resultMap="JoinTeamResult2">
select * from player p inner join team t on p.teamId=t.teamId
where t.teamId=#{id}
</select>
<!--方式2:直接引用关联对象的Mapper映射:要求连接查询
property="关联对象的属性名"
javaType="关联对象的类型"
resultMap="关联对象的命名空间中的resultMap"
-->
<resultMap id="JoinTeamResult2" type="com.kkb.pojo.Player" extends="baseResultMap">
<association property="team2" javaType="com.kkb.pojo.Team"
resultMap="com.kkb.mapper.TeamMapper.baseResultMap"></association>
</resultMap>
?teamMapper.xml中的baseResultMap??
<resultMap id="baseResultMap" type="com.kkb.pojo.Team">
<id column="teamId" property="teamId" javaType="int"></id>
<result column="teamName" property="teamName" javaType="string"></result>
<result column="location" property="location" javaType="string"></result>
<result column="createTime" property="createTime" javaType="date"></result>
</resultMap>
测试结果:
?
对一映射方式3:直接引用关联对象的单独查询的方法
要求:
1、不需要两表的连接查询 2、关联对象中已经存在被引用的查询方法(接口类中的方法)
就是分两步查先根据playerId查询出来的信息,再根据association标签中column属性指定第二次查询的列作为条件进行二次查询。
<select id="queryById3" resultMap="JoinTeamResult3">
select * from player where teamId=#{id}
</select>
<resultMap id="baseResultMap" type="com.kkb.pojo.Player">
<id column="playerId" property="playerId"></id>
<result column="playerName" property="playerName"></result>
<result column="playerNum" property="playerNum"></result>
<result column="teamId" property="teamId"></result>
</resultMap>
<!--方式3:直接引用关联对象的单独查询的方法:要求:关联对象的Maper中必须要求有单独的查询方法
property="关联对象的属性名"
javaType="关联对象的类型"
select="关联对象的单独查询的语句"
column="外键列"
-->
<resultMap id="JoinTeamResult3" type="Player" extends="baseResultMap">
<association property="team3" javaType="Team"
select="com.kkb.mapper.TeamMapper.queryById" column="teamId"></association>
</resultMap>
teamMapper接口中对应的方法。?
Team queryById(Integer teamId);
teamMapper.xml中的方法查询语句?
<select id="queryById" parameterType="int" resultType="com.kkb.pojo.Team">
select * from team where teamId=#{id}
</select>
测试结果:
?可以看到进行了两次查询
总结
开发中常用到第二种和第三种方式,其实第三种方式就是分两次查询,这一点也可以在service层次做到。
?对多关系的映射
修改实体类Team.java:
public class Team {
private Integer teamId;
private String teamName;
private String location;
private Date createTime;
//一对多的体现:一方持有多方的对象 分两种方法介绍
private List<Player> playerList1;//关联对象--一个球队可以拥有多个球员
private List<Player> playerList2;//关联对象--一个球队可以拥有多个球员
//get 和set 方法 toString方法自行补充
}
TeamMapper.java接口中添加方法:
public interface TeamMapper {
Team queryById1(int teamId);
Team queryById2(int teamId);
}
PlayerMapper.java接口中添加方法:? 第二种方法要用到
public interface PlayerMapper {
List<Player> queryByTeamId(int teamId);
}
PlayerMapper.xml添加如下内容:
<select id="queryByTeamId" resultType="Player">
select * from player where teamId=#{id}
</select>
方式1:连接查询+引用关联对象的结果映射
一步查询? 需要inner join进行连接查询
?方式2:引用关联对象的单独查询的方法
分两部查询? ?需要引用的其他类的方法进行二次查询
TeamMapper.xml添加
<select id="queryById1" resultMap="joinResult1">
select * from team t join player p
on t.teamId=p.teamId where t.teamId=#{id};
</select>
<select id="queryById2" resultMap="joinResult2">
select * from team where teamId=#{id};
</select>
<!--方式1:
对多的连接查询:对多使用collection
property="关联对象的集合名称"
javaType="关联对象的集合类型"
ofType="关联对象的集合的泛型"
resultMap="引用关联对象的结果映射"
-->
<resultMap id="joinResult1" type="Team" extends="baseResultMap">
<collection property="playerList1" javaType="java.util.ArrayList" ofType="Player"
resultMap="com.kkb.mapper.PlayerMapper.baseResultMap"></collection>
</resultMap>
<!--方式2:
对多的连接查询:对多使用collection
property="关联对象的集合名称"
javaType="关联对象的集合类型"
ofType="关联对象的集合的泛型"
select="引用关联对象的单独查询的方法":使用的前提是关联对象中该方法可用
column="引用关联对象的单独查询的方法的参数,一般是外键"
-->
<resultMap id="joinResult2" type="Team" extends="baseResultMap">
<collection property="playerList2" javaType="java.util.ArrayList"
select="com.kkb.mapper.PlayerMapper.queryByTeamId" column="teamId"></collection>
</resultMap>
测试:
public class TestPlayerMapper {
TeamMapper teamMapper=MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
/**
* 多关系查询 连接查询
*/
@Test
public void test04() {
Team team = teamMapper.queryById1(1005);
System.out.println(team);
List<Player> playerList1 = team.getPlayerList1();
for (Player player : playerList1) {
System.out.println(player);
}
}
/**
* 多关系查询 两次查询
*/
@Test
public void test05() {
Team team = teamMapper.queryById2(1003);
System.out.println(team);
List<Player> playerList2 = team.getPlayerList2();
for (int i = 0; i < playerList2.size(); i++) {
System.out.println(playerList2.get(i));
}
}
}
测试结果:
tset04
?tset05
|