MyBatis中联表查询的实现
在使用数据库时,我们经常会需要联表查询,把数据库b的信息整合到数据库a一并查询,就类似于老师于学生,工作和员工的关系。
而Mybatis就提供了一些这样的配置标签来帮助我们进行联表操作,简化我们的操作:association和collection
每个标签还都分别有两种查询方法:1:按查询嵌套处理 2:按结果嵌套处理
1:association(多对一)
association对象主要针对多个字段和同一个字段都有联系时,也就是多对一的情况。
MySQL数据库架构:
(数据库中的mybatis_test在下文会解释成user表)
实体类:
@Data //@Data注解可以帮助我们免去抒写GET,SET,ToString,有参,无参构造
//需要安装Lombok插件和maven依赖(或者jar包)
public class Work {
private int id;
private String name;
}
@Data
public class User {
private int id;
private String name;
//多个员工对应一个工作,即多对一
private Work work;
}
mapper:
public interface UserMapper {
public List<User> getUser();
}
public interface WorkMapper {
}
MyBatis 核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="com.nicht.pojo.User" alias="User"/>
<typeAlias type="com.nicht.pojo.Work" alias="Work"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/web_work?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"/>
<property name="username" value="root"/>
<property name="password" value="123321"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--这里填写和mapper的xml的路径来进行配置连接 -->
<mapper resource="UserMapper.xml"/>
<mapper resource="WorkMapper.xml"/>
</mappers>
</configuration>
1.按查询嵌套处理
按查询嵌套处理的方式:
先查询a表,然后根据a表中提供的信息再查询b表,最后把b表中查询的内容拼接到a表中,然后得出查询结果
<?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文件路径-->
<mapper namespace="com.nicht.mapper.UserMapper">
<select id="getUser" resultMap="UserWork">
select * from web_work.mybatis_test
</select>
<resultMap id="UserWork" type="User">
<association property="work" column="wid" javaType="Work" select="getWork"/>
<!--property:User类中对应的元素,column:表中所对应的字段
javaType:所查询到的字段所返回对应的实体类
select:所要使用的查询标签的id
根据这些属性的定义,MyBatis就会去调用下面那个select标签
把查询到的结果拼接到上面所查询的表中
且上面所查询到的coulumn就会传递到下面的select中,填入参数
当column只有一个的时候,上下id不一样也不会引起冲突,就一个嘛-->
</resultMap>
<select id="getWork" resultType="Work">
select * from web_work.work where id = #{id}
</select>
</mapper>
测试:
public class test {
@Test
public void selectUser() {
SqlSession session = MyBatisUtils.getSession();
//UserMapper.class中用到了反射的原理
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.getUser();
for (User user : users){
System.out.println(user);
}
session.close();
}
}
2.按结果嵌套处理
按查询嵌套处理的方式:
一开始就把a,b表中的内容查询出来,然后再根据查出来的字段分配好对应的实体类属性,虽较为理解,但sql语句抒写复杂。
<?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文件路径-->
<mapper namespace="com.nicht.mapper.UserMapper">
<select id="getWork2" resultMap="UserWork2" >
select m.id mid, m.name mname , w.name wname
from mybatis_test m,Work w
where m.wid = w.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<id property="id" column="mid"/>
<result property="name" column="mname"/>
<association property="work" javaType="Work">
<result property="name" column="wname"/>
</association>
</resultMap>
</mapper>
测试页面和上面的按查询嵌套方式处理一样
2:collection(一对多)
collection标签对应的就是一个字段和多个其他字段都有联系时,也就是一对多的情况。
在一对多的案例中,我们就是主要对Work表作为主要操作的地方了
实体类:
@Data //@Data注解可以帮助我们免去抒写GET,SET,ToString,有参,无参构造
//需要安装Lombok插件和maven依赖(或者jar包)
public class Work {
private int id;
private String name;
//一个工作对应多个员工
private List<User> users;
}
@Data
public class User {
private int id;
private String name;
private int wid;
}
mapper:
public interface UserMapper {
}
public interface WorkMapper {
public Work getWork(int id);
}
1.按结果嵌套处理
记得在mybatis核心配置文件中配置mapper
<mapper namespace="com.kuang.mapper.TeacherMapper">
<!--
集合使用collection!
JavaType和ofType都是用来指定对象类型的
JavaType是用来指定pojo中属性的类型
ofType指定的是映射到list集合属性中pojo的类型。
-->
<select id="getWork" resultMap="WorkUser">
select m.id mid, m.name mname , w.name wname, w.id wid
from mybatis_test m,user u
where u.wid = w.id and w.id=#{id}
</select>
<resultMap id="WorkUser" type="Work">
<result property="name" column="wname"/>
<collection property="users" ofType="User" javaType="ArrayList">
<result property="id" column="uid" />
<result property="name" column="uname" />
<result property="wid" column="wid" />
</collection>
</resultMap>
</mapper>
测试:
@Test
public void selectWork(){
SqlSession session = MybatisUtils.getSession();
WorkMapper mapper = session.getMapper(WorkMapper.class);
Work work = mapper.getWork(1);
System.out.println(work.getName();
System.out.println(work.getUsers();
}
2.按查询嵌套处理
<select id="getWork" resultMap="WorkUser">
select * from Work where id = #{id}
</select>
<resultMap id="WorkUser" type="Work">
<!--column是一对多的外键 , 写的是一的主键的列名-->
<collection property="users" javaType="ArrayList" ofType="User" column="id" select="getUser"/>
</resultMap>
<!--根据work表中的id再去查询user表中所对应的外键wid -->
<select id="getUser" resultType="User">
select * from mybatis_test where wid = #{id}
</select>