Mybatis的查询、关联查询
使用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的查询、关联查询相关推荐
- mybatis中的关联查询
mybatis中的关联查询 (尊重劳动成果,转载请注明出处:https://blog.csdn.net/qq_39778516/article/details/84191429 consistence ...
- mybatis一对多关联查询两种方式
mybatis一对多关联查询两种方式 前提: 方式一: 方式二: 前提: 现在有两张表,学生表跟教师表,一个教师对应多个学生 教师表: CREATE TABLE `teacher` (`id` int ...
- 14、mybatis多表关联查询 association定义关联对象封装规则及懒加载
文章目录 1.使用association单步查询 1).EmployeeMapper 2).EmployeeMapper.xml 3).Test 2.使用association进行分步查询 4).De ...
- 13、mybatis多表关联查询级联属性
文章目录 1.创建表结构 2.EmployeeMapper接口 3.EmployeeMapper.xml 4.Test 1.创建表结构 CREATE TABLE `mybatis`.`dept` (` ...
- mybatis collection_MyBatis之关联查询
前言 我们进行数据库查询时往往需要的不止一张表的数据,需要将多张表的数据一起查询出来,大家学习过数据库的连接查询,那么在MyBatis中如何将有关系的多张表数据进行关联查询呢. 表的结构 商品和订单是 ...
- mybatis 多表关联查询_Java修行第041天--MyBatis框架(下)--多表查询
1 解决列名和属性名不一致问题 如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库 ...
- 【mybatis】一对一关联查询
mybatis: 一对一关联查询 注意 代码部分 实体类(extity) mybatis mapper service controller 注意 在.xml文件编写中有报错,The content ...
- Mybatis多表关联查询(一对多关联查询)
1.Mybatis一级缓存与二级缓存 目的:提高查询效率,降低数据库查询压力,提升系统整体性能. 一级缓存:默认开启,Session级别,同一个会话内生效. 命中缓存的情况:statementid.S ...
- Mybatis一对多关联查询,返回值Map,字段自动映射
功能描述 由于查询字段和表名都要支持动态配置,故查询返回值需要为List<Map<String,Object>>,不定义值对象. 查询结果列需要支持自动映射,不配置类属性和数据 ...
- mybatis一对多关联查询将结果封装到嵌套list
DishDto中有个List集合保存DishFlavor对象,DishFlavor根据关联查询获得,一个dish对应多个dishflavor.想要联合查询自动将DishFlavor封装成集合需要用co ...
最新文章
- 公司各个阶段 CTO 需要做什么?(下篇)
- 历史回顾,各种编程工具的应用与我的发展历程之二(VB)
- 信息与计算机科学好学吗,计算机科学与技术好学吗?
- 【学习】Android开入门教程
- Java 分页,两种方式的分页,即取即用的代码,不客气
- 教师资格证考试计算机知识题库,教师资格证考试题库
- php面试专题---MYSQL查询语句优化
- 2017-3-23校内训练
- CSS3 Transform变形(2D转换)
- 变电站接地网的优化设计22437
- HDFS 读取、写入、遍历文件夹获取文件全路径、append
- #include 和前置声明
- STAP旁瓣干扰抑制与干扰对抗仿真
- 首个步态识别框架开源了
- linux系统安装pidgin,linux下QQ的安装(pidgin的安装)
- Linux TCP Timestamps 没鸟用
- kernel 选项详解(stlinux2.3) 2-2
- 机器学习评价指标(1)——灵敏度(sensitivity)/查准率/召回率(Recall)/和特异度(Specificity)
- 我用“电驴”抓肉鸡(转)
- [share]深入探讨PHP中的内存管理问题