一对一也就是 A 表的一条记录对应 B 表的一条记录,下面的测试数据中,从employee 表来看,一个员工对应一个部门,是一对一关系,如果从部门角度来看,则是一对多的关系,一个部门对应多个员工,本节主要研究一对一的关系。

数据表建立


新建数据表department,有两个字段,插入两条数据如下:

id dept_name
1 CIA
2 FSB

新建数据表employee,有三个字段,其中dept_id是外键,关联department表的主键id。插入数据如下:

id last_name dept_id
1 Tom 1
2 Jerry 2
3 Neo 1
4 Cypher 2

新建maven工程,添加依赖,主要是mybatis和mysql


<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>

3、编写数据库表对应的实体。


对于department表,对应实体如下:

package com.yefengyu.mybatis.entity;

public class Department
{
private Integer id; private String deptName; public Integer getId()
{
return id;
} public void setId(Integer id)
{
this.id = id;
} public String getDeptName()
{
return deptName;
} public void setDeptName(String deptName)
{
this.deptName = deptName;
} @Override
public String toString()
{
return "Department{" +
"id=" + id +
", deptName='" + deptName + '\'' +
'}';
}
}

对于employee表,实体如下,注意在Employee实体中把外键直接变成对于Department对象的引用。

package com.yefengyu.mybatis.entity;

public class Employee
{
private Integer id; private String lastName; private Department department; public Integer getId()
{
return id;
} public void setId(Integer id)
{
this.id = id;
} public String getLastName()
{
return lastName;
} public void setLastName(String lastName)
{
this.lastName = lastName;
} public Department getDepartment()
{
return department;
} public void setDepartment(Department department)
{
this.department = department;
} @Override
public String toString()
{
return "Employee{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", department=" + department +
'}';
}
}

编写mapper接口


package com.yefengyu.mybatis.mapper;

import com.yefengyu.mybatis.entity.Employee;

public interface EmployeeMapper
{
Employee getEmployee(Integer id);
}

根据员工ID查询员工信息和部门信息

编写mapper映射文件(本节重点)


一对一查询mapper文件有三种编写方式,分别是:

1、级联属性法

<?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 namespace="com.yefengyu.mybatis.mapper.EmployeeMapper">
<resultMap id="employee" type="com.yefengyu.mybatis.entity.Employee">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="d_id" property="department.id"/>
<result column="dept_name" property="department.deptName"/>
</resultMap> <select id="getEmployee" resultMap="employee">
select e.id id, e.last_name last_name, e.dept_id dept_id, d.id d_id,d.dept_name dept_name
from employee e, department d
where e.id = #{id} and e.dept_id = d.id
</select>
</mapper>

2、association嵌套结果集

<?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 namespace="com.yefengyu.mybatis.mapper.EmployeeMapper">
<!--
使用association定义关联的单个对象的封装规则;
-->
<resultMap id="employee" type="com.yefengyu.mybatis.entity.Employee">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/> <!-- association可以指定联合的javaBean对象
property="department":指定哪个属性是联合的对象
javaType:指定这个属性对象的类型[不能省略]
-->
<association property="department" javaType="com.yefengyu.mybatis.entity.Department">
<id column="d_id" property="id"/>
<result column="dept_name" property="deptName"/>
</association> </resultMap> <select id="getEmployee" resultMap="employee">
select e.id id, e.last_name last_name, e.dept_id dept_id, d.id d_id,d.dept_name dept_name
from employee e, department d
where e.id = #{id} and e.dept_id = d.id
</select>
</mapper>

3、association分步查询法

1)首先需要创建一个关于department的接口

package com.yefengyu.mybatis.mapper;

import com.yefengyu.mybatis.entity.Department;

public interface DepartmentMapper
{
public Department getDeptById(Integer id);
}

2)其次编写该接口的映射文件

<?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 namespace="com.yefengyu.mybatis.mapper.DepartmentMapper">
<select id="

getDeptById

" resultType="com.yefengyu.mybatis.entity.Department">
select id,dept_name from department where id = #{id}
</select>
</mapper>

3)现在定义一个查询employee的接口(级联属性法和association嵌套结果集测试时已经建立该接口)

package com.yefengyu.mybatis.mapper;

import com.yefengyu.mybatis.entity.Employee;

public interface EmployeeMapper
{
Employee getEmployee(Integer id);
}

4)编写该接口对应的映射文件

<?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 namespace="com.yefengyu.mybatis.mapper.EmployeeMapper">
<resultMap id="employee" type="com.yefengyu.mybatis.entity.Employee">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<!-- association定义关联对象的封装规则
select:表明当前属性是调用select指定的方法查出的结果
column:指定将哪一列的值传给这个方法 流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
-->
<association property="department"
select="com.yefengyu.mybatis.mapper.DepartmentMapper.getDeptById"
column="dept_id">
</association>
</resultMap> <select id="getEmployee" resultMap="employee">
select * from employee where id = #{id}
</select>
</mapper>

延迟加载:

每次查询Employee对象的时候,都将部门信息一起查询出来。但是想要部门信息在我们使用的时候再去查询,如果不需要就不查询,怎么实现?分步查询的基础上加两个配置:

<!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题  -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。

新建一个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>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8&amp;allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/EmployeeMapper.xml"/>
<mapper resource="mapper/DepartmentMapper.xml"/>
</mappers>
</configuration>

测试


通用测试代码:

public static void main(String[] args)
throws IOException
{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
try
{
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = mapper.getEmployee(1);
System.out.println(employee);
}
finally
{
sqlSession.close();
}
}

准对于延迟加载的特殊测试,对于上面测试代码,如果只打印员工名

System.out.println(employee.getLastName());

那么不会查询部门表

Created connection 1776957250.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69ea3742]
==> Preparing: select * from employee where id = ?
==> Parameters: 1(Integer)
<== Columns: id, last_name, dept_id
<== Row: 1, tom, 1
<== Total: 1
tom
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69ea3742]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@69ea3742]
Returned connection 1776957250 to pool.

如果打印部门相关信息,例如通用测试的代码(由于实体都重写了toString方法,因此打印employee的时候也打印了department,所以也是使用了部门信息),此时的日志为:

Created connection 1776957250.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69ea3742]
==> Preparing: select * from employee where id = ?
==> Parameters: 1(Integer)
<== Columns: id, last_name, dept_id
<== Row: 1, tom, 1
<== Total: 1
==> Preparing: select id,dept_name from department where id = ?
==> Parameters: 1(Integer)
<== Columns: id, dept_name
<== Row: 1, A
<== Total: 1
Employee{id=1, lastName='tom', department=Department{id=1, deptName='A'}}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@69ea3742]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@69ea3742]
Returned connection 1776957250 to pool.

mybatis关联查询之一对一查询的更多相关文章

  1. mybatis学习笔记(10)-一对一查询

    mybatis学习笔记(10)-一对一查询 标签: mybatis mybatis学习笔记10-一对一查询 resultType实现 resultMap实现 resultType和resultMap实 ...

  2. MyBatis 高级查询之一对一查询(九)

    高级查询之一对一查询 查询条件:根据游戏角色ID,查询账号信息 我们在之前创建的映射器接口 GameMapper.java 中添加接口方法,如下: /** * 根据角色ID查询账号信息 * @para ...

  3. Mybatis高级查询之一对一查询的四种方法

    目录 1. 一对一查询 1.1 一对一嵌套结果查询 1.2 使用resultMap配置一对一映射 1.3 使用resultMap的association标签配置一对一映射 1.4 associatio ...

  4. Mybatis多表查询之一对一查询的多种实现-XML配置

    Mybatis 中对于多表查询提供了非常强大的实现方式,主要是通过resultMap的结果映射对于多表查询后的返回值进行封装,让我们来看一下官网上对于resultMap的解释:resultMap 元素 ...

  5. mybatis关联集合List&分布查询传递多列值

    场景:查询部门的同时,要求查询此部门下的所有用户. 部门(Department) private Integer id; private String departmentName; private ...

  6. Django【第7篇】:Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)

    django之跨表查询及添加记录 一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); ...

  7. 7.Mybatis关联表查询(这里主要讲的是一对一和一对多的关联查询)

    在Mybatis中的管理表查询这里主要介绍的是一对一和一对多的关联查询的resultMap的管理配置查询,当然你也可以用包装类来实现.不过这里不说,做关联查询的步骤可以简单的总结为以下的几步: 1.分 ...

  8. mybatis进阶--一对一查询

    所谓的一对一查询,就是说我们在查询一个表的数据的时候,需要关联查询其他表的数据. 需求 首先说一个使用一对一查询的小需求吧:假设我们在查询某一个订单的信息的时候,需要关联查询出创建这个订单对应的用户信 ...

  9. Spring+SpringMVC+MyBatis深入学习及搭建(六)——MyBatis关联查询

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6923464.html 前面有将到:Spring+SpringMVC+MyBatis深入学习及搭建(五)--动 ...

随机推荐

  1. Python : Data Encapsulation

    Python : Data Encapsulation The following table shows the different behaviour: Name Notation Behavio ...

  2. style中各种选择器

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. JVM(4)之 使用MAT排查堆溢出

    开发十年,就只剩下这套架构体系了! >>>   接下来讲解如何设置以及当发生堆溢出的时候怎么排查问题.先看一小段代码:     代码中使用了一个无限循环来为list添加对象,如果采用 ...

  4. Vue 踩坑日志 - 有关路由传参的坑

    1.有关路由传参 vue中当通过params传过去的参数刷新页面以后会消失,所以可以用query传参.但此时又会出现另一个坑,刷新后数据仍在.但这是针对单个的某个变量的. 如果传入一个对象的话,刷新页 ...

  5. tensorflow的阶、形状、数据类型

    张量的阶.形状.数据类型 TensorFlow用张量这种数据结构来表示所有的数据.你可以把一个张量想象成一个n维的数组或列表.一个张量有一个静态类型和动态类型的维数.张量可以在图中的节点之间流通. 阶 ...

  6. A星寻路

    逻辑代码 using System.Collections.Generic; using System.Text; using UnityEngine; namespace Game { public ...

  7. Python中集合类型的使用

    集合类型 多个不重复元素的无序组合 集合类型的表示 建立非空集合的方式可以用{}来表示 采用set()来表示 集合类型的操作符 S|T 返回一个新集合,这个集合包含S与T中的所有元素. S-T 返回一 ...

  8. CentOS7.6系统安装zabbix3.4.8客户端

    一.     准备安装包 将本地的zabbix-3.4.8软件包上传至服务器, 二.     安装依赖包 安装依赖包:yum install gcc* pcre* psmisc -y 三.     安 ...

  9. openstack组件之nova

    Nova常用命令  1.查看vm列表 nova listnova list --all 2.查看镜像列表  nova image-list   3.查看卷列表 nova voluma-list 4.查 ...

  10. 前端每日实战:69# 视频演示如何用纯 CSS 创作一个单元素抛盒子的 loader

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qKwXbx 可交互视频 此视频是可 ...