使用Mybatis进行查询

查询结果的映射

Mybatis通过<select>进行查询。通过<resultMap>将查询结果封装成实体类:

<resultMap id="deptMap" type="Dept"><!--<![CDATA[<id>是主键标签]]> --><!--<![CDATA[<property是类中的属性名,column是sql语句中查询出来的字段>]]> --><id property="id" column="ID"/><!--<![CDATA[<result>是主键标签]]> --><result property="name" column="NAME"/>
</resultMap><select id="getAllDept" resultMap="deptMap">select ID,NAME from DEPT
</select>

<resultMap>用于封装结果集。一个Mapper中可以有多个<resultMap>,每个<resultMap>的id是唯一的。type用于指定结果集对应的实体类类型。type="Dept"即将<resultMap>中所有的属性都对应到Dept类中。

对应关系如下图所示:

我们可以这样理解,一个查询语句,从查询出结果,到封装成实体类,经历如下步骤:

\1. 当使用<select>查询出结果后,会根据<select>中resultMap=”deptMap”找到id=”deptMap”的<resultMap>标签

\2. 根据<resultMap>的type=”Dept”找到Dept对应的类,这里Dept是别名,也可以写成全路径pojo.Dept。

\3. <resultMap>中的<result>标签,将查询结果中的字段与实体类中的属性对应起来,property=”name”是找到Dept类中的name属性,column=”NAME”中NAME是SQL语句中NAME字段对应的值,通过setName方法将结果集绑定到name属性上。

需要注意的是column=”NAME”中的NAME不是数据库中的字段名,而是select语句中查询出来的字段别名,因为我们可以用as去给字段起别名。如上面改变上面的语句,为查询结果起别名,对应的column也要改变:

测试代码:

@Test
public void testSelectAll() {//当查询结果有多个的时候,使用selectListList<Dept> deptList = session.selectList("DEPT.getAllDept");for (Dept dept : deptList) {System.out.println(dept.getName());}
}

session.selectList适用于查询结果是一个集合的情况,如果实现按主键查询,则使用session.selectOne方法。如按主键查询:

<select id="getDeptById" parameterType="int" resultMap="deptMap">select ID,NAME from DEPT where ID=#{id}
</select>

测试代码:

@Test
public void testSelectOne() {Dept dept = session.selectOne("DEPT.getDeptById", 21);System.out.println(dept.getName());
}

resultMap还支持继承:

<resultMap id="deptMap" type="Dept"><id column="ID"  property="id" /><result column="NAME" property="name"/>
</resultMap><resultMap id="deptMapChild" type="Dept" extends="deptMap"><!--这里写新的<result>-->
</resultMap>

当我们又多个<resultMap>的时候,有些属性<result>的配置可以复用,就可以使用extends进行继承,上面的示例中,deptMapChild可以使用deptMap中的配置,具体的示例,请参照3.2.2中的deptMapWithEmployee

关联查询

3.2.1 一对一、多对一

本节的操作使用EmployeeMapper.xml,请提前创建文件并将EmployeeMapper.xml的namespace设置为”EMPLOYEE”。
Mybatis中一对一和多对一的配置一样。以员工EMPLOYEE为例。多个员工同属于一个部门,所以员工对部门是多对一。

员工实体类:

package pojo;
import java.util.Date;
public class Employee {private Integer id;private String name;private Dept dept;private String job;private Float salary;private Date hireDate;//getter/setter方法略
}

如果查询出员工的时候要查询出部门名,可以编写如下语句:

<select id="getEmployeeWithDept" resultMap="employeeMap">select E.ID, E.NAME ,E.JOB, E.SALARY, E.HIRE_DATE, E.DEPT_ID, D.NAME DEPT_NAMEfrom EMPLOYEE Einner join DEPT D ON E.DEPT_ID=D.ID
</select>

对应的resultMap配置如下:

<resultMap id="employeeMap" type="Employee"><id property="id" column="ID"/><result property="name" column="NAME"/><result property="job" column="JOB"/><result property="salary" column="SALARY"/><result property="hireDate" column="HIRE_DATE"/><result property="dept.id" column="DEPT_ID"/><result property="dept.name" column="DEPT_NAME"/>
</resultMap>

通过dept.id和dept.name这种级联的方式给Employee类中dept这个属性的id和name赋值。

测试代码:

public void testManyToOne() {List<Employee> empList = session.selectList("EMPLOYEE.getEmployeeWithDept");for (Employee employee : empList) {System.out.println(employee.getName() + "的部门:"+ employee.getDept().getName());}
}

结果集employeeMap也可以使用association进行优化:

<resultMap id="employeeMap2" type="Employee"><id property="id" column="ID"/><result property="name" column="NAME"/><result property="job" column="JOB"/><result property="salary" column="SALARY"/><result property="hireDate" column="HIRE_DATE"/><!--使用association将属于Dept的属性进行封装,不再使用dept.id--><association property="dept" javaType="Dept"><result property="id" column="DEPT_ID"/><result property="name" column="DEPT_NAME"/></association>
</resultMap>

因为我们在DeptMapper.xml已经为Dept配置了结果集,所以上面的<association>可以通过resultMap引用其他的结果集:

<!--引用DEPT.deptMap-->
<association property="dept" resultMap="DEPT.deptMap">
</association>

<association>标签还有一个select属性,可以通过一个查询语句得到结果集并进行映射。如:

<resultMap id="employeeMap3" type="Employee"><id property="id" column="ID"/><result property="name" column="NAME"/><result property="job" column="JOB"/><result property="salary" column="SALARY"/><result property="hireDate" column="HIRE_DATE"/><!--通过select调用DEPT.getDeptById--><association property="dept" column="DEPT_ID" select="DEPT.getDeptById" ></association>
</resultMap>
<select id="getAllEmp" resultMap="employeeMap3">select * from EMPLOYEE
</select>

执行getAllEmp这个语句,我们只查询了EMPLOYEE表,没有查询DEPT表,在结果映射到employeeMap3的时候,associstion通过select指定的语句,去调用了DEPT.getDeptById进行查询,并将结果集封装到dept中。控制台打印sql如下:

可以看到,执行的流程是先查询出所有的EMPLOYEE,然后遍历结果集,根据每条查询结果的DEPT_ID去查询了DEPT表。直接使用join会执行一条语句,而在<associstion>中使用select,会执行n+1条。n是主表的查询结果集的条数,效率较低。

3.2.2 一对多、多对多

一对多、多对多的配置都是通过<collection>进行的。以一对多为例,一个部门DEPT有多个员工EMPLOYEE。

Dept实体类中添加Employee集合:

package pojo;
import java.util.List;
public class Dept {private Integer id;private String name;private List<Employee> employees;// getter/setter方法略
}

如果查询部门的时候要查询出部门所有的员工,sql语句为:

<select id="getDeptWith" resultMap="deptMapWithEmployee">select D.ID, D.NAME, E.ID EMP_ID, E.NAME EMP_NAMEfrom DEPT Dleft join EMPLOYEE E ON E.DEPT_ID=D.ID
</select>

为了简化操作,我们只联合查询EMPLOYEE的ID和NAME两个属性。

对应的resultMap映射为:

<!--extends实现继承id=继承deptMap的resultMap-->
<resultMap id="deptMapWithEmployee" type="Dept" extends="deptMap"><!--collection用于映射一个集合--><collection property="employees" ofType="Employee" ><id property="id" column="EMP_ID"/><result property="name" column="EMP_NAME"/></collection>
</resultMap>

<collection>也支持select属性:

<resultMap id="deptMapWithEmployee2" type="Dept" extends="deptMap"><!--collection用于映射一个集合--><collection property="employees" ofType="Employee" select="EMPLOYEE.getEmpByDept" column="ID"></collection>
</resultMap><select id="getAllDept2" resultMap="deptMapWithEmployee2">select ID,NAME from DEPT
</select>

<collection>的select调用了EMPLOYEE.getEmpByDept,需要提前在EmployeeMapper.xml中写好对应的语句:

<select id="getEmpByDept" resultMap="employeeMap" parameterType="int">select ID,NAME FROM EMPLOYEE where DEPT_ID=#{deptid}
</select>

执行getAllDept2,可以看到控制台上的输出:

<association>一样,直接使用join会执行一条语句,而在<collection>中使用select,会执行n+1条。n是主表的查询结果集的条数,效率较低

Mybatis的查询、关联查询相关推荐

  1. mybatis中的关联查询

    mybatis中的关联查询 (尊重劳动成果,转载请注明出处:https://blog.csdn.net/qq_39778516/article/details/84191429 consistence ...

  2. mybatis一对多关联查询两种方式

    mybatis一对多关联查询两种方式 前提: 方式一: 方式二: 前提: 现在有两张表,学生表跟教师表,一个教师对应多个学生 教师表: CREATE TABLE `teacher` (`id` int ...

  3. 14、mybatis多表关联查询 association定义关联对象封装规则及懒加载

    文章目录 1.使用association单步查询 1).EmployeeMapper 2).EmployeeMapper.xml 3).Test 2.使用association进行分步查询 4).De ...

  4. 13、mybatis多表关联查询级联属性

    文章目录 1.创建表结构 2.EmployeeMapper接口 3.EmployeeMapper.xml 4.Test 1.创建表结构 CREATE TABLE `mybatis`.`dept` (` ...

  5. mybatis collection_MyBatis之关联查询

    前言 我们进行数据库查询时往往需要的不止一张表的数据,需要将多张表的数据一起查询出来,大家学习过数据库的连接查询,那么在MyBatis中如何将有关系的多张表数据进行关联查询呢. 表的结构 商品和订单是 ...

  6. mybatis 多表关联查询_Java修行第041天--MyBatis框架(下)--多表查询

    1 解决列名和属性名不一致问题 如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库 ...

  7. 【mybatis】一对一关联查询

    mybatis: 一对一关联查询 注意 代码部分 实体类(extity) mybatis mapper service controller 注意 在.xml文件编写中有报错,The content ...

  8. Mybatis多表关联查询(一对多关联查询)

    1.Mybatis一级缓存与二级缓存 目的:提高查询效率,降低数据库查询压力,提升系统整体性能. 一级缓存:默认开启,Session级别,同一个会话内生效. 命中缓存的情况:statementid.S ...

  9. Mybatis一对多关联查询,返回值Map,字段自动映射

    功能描述 由于查询字段和表名都要支持动态配置,故查询返回值需要为List<Map<String,Object>>,不定义值对象. 查询结果列需要支持自动映射,不配置类属性和数据 ...

  10. mybatis一对多关联查询将结果封装到嵌套list

    DishDto中有个List集合保存DishFlavor对象,DishFlavor根据关联查询获得,一个dish对应多个dishflavor.想要联合查询自动将DishFlavor封装成集合需要用co ...

最新文章

  1. 公司各个阶段 CTO 需要做什么?(下篇)
  2. 历史回顾,各种编程工具的应用与我的发展历程之二(VB)
  3. 信息与计算机科学好学吗,计算机科学与技术好学吗?
  4. 【学习】Android开入门教程
  5. Java 分页,两种方式的分页,即取即用的代码,不客气
  6. 教师资格证考试计算机知识题库,教师资格证考试题库
  7. php面试专题---MYSQL查询语句优化
  8. 2017-3-23校内训练
  9. CSS3 Transform变形(2D转换)
  10. 变电站接地网的优化设计22437
  11. HDFS 读取、写入、遍历文件夹获取文件全路径、append
  12. #include 和前置声明
  13. STAP旁瓣干扰抑制与干扰对抗仿真
  14. 首个步态识别框架开源了
  15. linux系统安装pidgin,linux下QQ的安装(pidgin的安装)
  16. Linux TCP Timestamps 没鸟用
  17. kernel 选项详解(stlinux2.3) 2-2
  18. 机器学习评价指标(1)——灵敏度(sensitivity)/查准率/召回率(Recall)/和特异度(Specificity)
  19. 我用“电驴”抓肉鸡(转)
  20. [share]深入探讨PHP中的内存管理问题

热门文章

  1. 跨站请求伪造CSRF防护方法
  2. Bash中的位置参数和特殊参数
  3. Block的引用循环问题 (ARC non-ARC)
  4. js中的DOM操作汇总
  5. linux高级命令组合
  6. Wordpress空间和域名的备份
  7. AngularJS学习(二)
  8. JavaScript解决e6不支持不支持max-width,max-height的问题的方法
  9. JavaScript算法(实例八)递归计算每个月的兔子总数【斐波那契数列】
  10. android反射开启通知_作为Android开发者 你真的知道app从启动到主页显示的过程吗?...