复杂查询环境
多对一和一对多
多个工作者对应一个协调人
对于工作者(worker)而言,多个工作者关联一个协调人(coordinator)(多对一,关联)
对于协调人而言,一个协调人有很多工作者(一对多,集合)
在程序开发中,也会遇到类似的情况,这时就会涉及到Mybatis中结果映射的association
和 collection
实例
创建数据表
coordinator表
CREATE TABLE `coordinator`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO coordinator(`id`, `name`) VALUES(1, "Alex");
worker表
CREATE TABLE `worker`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`cid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`cid`) REFERENCES `coordinator` (`id`)
)ENGINE = INNODB DEFAULT CHARSET=utf8mb4;
INSERT INTO `worker` (`id`, `name`, `cid`) VALUES (1, '小明', '1');
INSERT INTO `worker` (`id`, `name`, `cid`) VALUES (2, '小红', '1');
INSERT INTO `worker` (`id`, `name`, `cid`) VALUES (3, '小方', '1');
INSERT INTO `worker` (`id`, `name`, `cid`) VALUES (4, '小芳', '1');
INSERT INTO `worker` (`id`, `name`, `cid`) VALUES (5, '小王', '1');
环境搭建
创建核心配置文件(mybatis-config.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
</configuration>
创建配置文件(db.properties)
username = root
password = root
url = jdbc:mysql://localhost:3306/mybatis
driver = com.mysql.cj.jdbc.Driver
创建工具类(MybatisUtil)
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
文件准备
①导入相关依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
②新建实体类
Coordinator类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Coordinator {
private int id;
private String name;
}
Worker类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Worker {
private int id;
private String name;
//工作者需要关联协调人
private Coordinator coordinator;
}
③创建Mapper接口
CoordinatorMapper
public interface CoordinatorMapper {
@Select("select * from coordinator where id = #{cid}")
Coordinator select(@Param("cid") int id);
}
WorkerMapper
public interface WokerMapper {
}
④创建Mapper.xml
CoordinatorMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.louis.dao.CoordinatorMapper">
</mapper>
WorkerMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.louis.dao.WokerMapper">
</mapper>
⑤在核心配置文件中绑定注册Mapper接口或文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="com.louis.dao.CoordinatorMapper"/>
<mapper class="com.louis.dao.WokerMapper"/>
</mappers>
</configuration>
⑥测试是否成功
public class MyTest {
static Logger logger = Logger.getLogger(MyTest.class);
@Test
public void test(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
CoordinatorMapper mapper = sqlSession.getMapper(CoordinatorMapper.class);
Coordinator select = mapper.select(1);
logger.info(select);
sqlSession.close();
}
}
//注意导入Logger为:import org.apache.log4j.Logger;
特别提醒:以上只是为了测试配置文件是否正确。
多对一处理
WorkerMapper接口
public interface WorkerMapper {
//查询所有的工作人员和它们对应的协调人的信息
List<Worker> getWorker2();
List<Worker> getWorker();
}
方式一(按照查询嵌套处理)
WorkerMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.louis.dao.WorkerMapper">
<!--<select id="getWorker" resultType="com.louis.pojo.Worker">-->
<!--
思路:
1、查询所有的工作人员信息
2、根据查询出来的工作人员的cid,寻找对应的协调人
-->
<!--select w.id, w.name,
c.name from worker as w,
coordinator as c
where w.tid = c.id;-->
<!--select * from worker;-->
<!--</select>-->
<select id="getWorker" resultMap="WorkerCoordinator">
select * from worker;
</select>
<resultMap id="WorkerCoordinator" type="com.louis.pojo.Worker">
<!--column 数据库中的字段, property实体类中的属性-->
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性我们需要单独做处理 对象使用association 集合使用collection-->
<association property="coordinator" column="cid" javaType="com.louis.pojo.Coordinator" select="getCoordinator"/>
</resultMap>
<select id="getCoordinator" resultType="com.louis.pojo.Coordinator">
select * from coordinator where id = #{id};
</select>
</mapper>
测试
@Test
public void getWorker(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
WorkerMapper mapper = sqlSession.getMapper(WorkerMapper.class);
List<Worker> worker = mapper.getWorker();
System.out.println("worker = " + worker);
sqlSession.close();
}
//结果
worker = [Worker(id=1, name=小明, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=2, name=小红, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=3, name=小方, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=4, name=小芳, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=5, name=小王, coordinator=Coordinator(id=1, name=Alex))]
方式二(按照结果嵌套处理)
WorkerMapper.xml
<!--
方式二:按照结果嵌套处理
思路:
1、查询所有的工作人员信息
2、根据查询出来的工作人员的cid,寻找对应的协调人
-->
<select id="getWorker2" resultMap="WorkerCoordinator02">
<!--使用我们常用的查询语句,并且相应的给一些别名-->
select w.id as wid, w.name as wname, c.name as cname
from worker as w, coordinator as c
where w.cid = c.id;
</select>
<resultMap id="WorkerCoordinator02" type="com.louis.pojo.Worker">
<result property="id" column="wid"/>
<result property="name" column="wname"/>
<association property="coordinator" javaType="com.louis.pojo.Coordinator">
<result property="name" column="cname"/>
</association>
</resultMap>
测试
@Test
public void getWorker2(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
WorkerMapper mapper = sqlSession.getMapper(WorkerMapper.class);
List<Worker> worker = mapper.getWorker2();
System.out.println("worker = " + worker);
sqlSession.close();
}
//结果
worker = [Worker(id=1, name=小明, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=2, name=小红, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=3, name=小方, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=4, name=小芳, coordinator=Coordinator(id=1, name=Alex)),
Worker(id=5, name=小王, coordinator=Coordinator(id=1, name=Alex))]
一对多处理
比如一个协调人对应多个工作人员,对于协调人而言,就是一对多的关系,除了实体类外和多对一的环境相同。
实体类
Worker
public class Worker {
private int id;
private String name;
private int cid;
}
Coordinator
public class Coordinator {
private int id;
private String name;
//一个协调人协调多个工作人员
private List<Worker> worker;
}
CoordinatorMapper接口
public interface CoordinatorMapper {
//获取指定协调人下的所有工作人员和协调人的信息
Coordinator getCoordinatorTarget(@Param("cid") int cid);
Coordinator getCoordinatorTarget01(@Param("id") int id);
}
方式一(按照查询嵌套处理)
CoordinatorMapper.xml
<!--按查询嵌套处理-->
<select id="getCoordinatorTarget01" resultMap="CoordinatorWorker01">
select * from mybatis.coordinator where id = #{id}
</select>
<resultMap id="CoordinatorWorker01" type="com.louis.entity.Coordinator">
<result property="id" column="id"/>
<result property="name" column="name"/>
<collection property="worker" javaType="ArrayList" ofType="com.louis.entity.Worker" select="getWorkerById" column="id"/>
</resultMap>
<select id="getWorkerById" resultType="com.louis.entity.Worker">
select * from worker where cid = #{id}
</select>
测试
@Test
public void myTest01(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
CoordinatorMapper mapper = sqlSession.getMapper(CoordinatorMapper.class);
Coordinator coordinatorTarget = mapper.getCoordinatorTarget(1);
System.out.println("coordinatorTarget = " + coordinatorTarget);
sqlSession.close();
coordinatorTarget = Coordinator(id=1, name=Alex,
worker=[Worker(id=1, name=小明, cid=0),
Worker(id=2, name=小红, cid=0),
Worker(id=3, name=小方, cid=0),
Worker(id=4, name=小芳, cid=0),
Worker(id=5, name=小王, cid=0)])
方式二(按照结果嵌套处理)
CoordinatorMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.louis.dao.CoordinatorMapper">
<!--按结果嵌套查询-->
<select id="getCoordinatorTarget" resultMap="CoordinatorWorker">
select c.id, c.`name`, w.id as wid, w.`name`as wname
from coordinator as c, worker as w
where c.id = w.cid and c.id = #{cid}
</select>
<resultMap id="CoordinatorWorker" type="com.louis.entity.Coordinator">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性我们需要单独做处理 对象使用association 集合使用collection
javaType=""指定属性的类型,集合中泛型信息我们需要使用的是ofType
-->
<collection property="worker" ofType="com.louis.entity.Worker">
<result property="id" column="wid"/>
<result property="name" column="wname"/>
</collection>
</resultMap>
</mapper>
测试
@Test
public void myTest02(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
CoordinatorMapper mapper = sqlSession.getMapper(CoordinatorMapper.class);
Coordinator coordinator = mapper.getCoordinatorTarget01(1);
System.out.println("coordinator = " + coordinator);
sqlSession.close();
//结果
coordinatorTarget = Coordinator(id=1, name=Alex,
worker=[Worker(id=1, name=小明, cid=0),
Worker(id=2, name=小红, cid=0),
Worker(id=3, name=小方, cid=0),
Worker(id=4, name=小芳, cid=0),
Worker(id=5, name=小王, cid=0)])
注意:使用association
用于(多对一) 和collection
用于(一对多),此外
javaType
用来指定实体类中属性的类型
ofType
用来指定映射到List或集合中的pojo类型,泛型中的约束类型。如:List<worker>