一对一也就是 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. Quartz的简单使用

    一.Quartz 介绍 Quartz是Java领域最著名的.功能丰富的.开放源码的作业调度工具,几乎可以在所有的Java应用程序中集成--从小的单机应用到大的电子商务系统. Quartz可以用来执行成 ...

  2. ansiable介绍及安装

    ansible介绍: Ansible默认通过 SSH 协议管理机器. ssh协议介绍:https://www.cnblogs.com/yaozhiqiang/p/9944894.html 安装ansi ...

  3. Linux修改密码指令

    1.在选择系统菜单界面,按 "e" 进入编辑模式 2.在以字符串“Linux16”开头的行,将光标移动到该行的结尾,然后输入“init=/bin/bash”,按 "Ctr ...

  4. 初学Java 求最大公约数

    import java.util.Scanner; public class GreatesCommonDivisor { public static void main(String[] args) ...

  5. rabbitmq路由规则

    信道如何共用???? 几台机器共用一个channel 如何做到?

  6. Vue组件-组件组合

    组件设计初衷就是要配合使用的,最常见的就是形成父子组件的关系:组件 A 在它的模板中使用了组件 B. <html> <head> <title>Vue组件 A 在它 ...

  7. 7.搭建hyperledger fabric环境及启动——2019年12月12日

    2019年12月12日13:05:16 声明:从网络中学习整理实践而来. 1.介绍fabric Fabric 是一个面向企业应用的区块链框架,基于 Fabric 的开发可以粗略分为几个层面: 1. 参 ...

  8. STN空间变换网络

    STN的主要思想是通过网络学习一个变化参数,然后计算出新图在原图上对应的坐标,再通过某种填充方法填充新图. 使得得到的新图很好的适应nn训练.可以理解为是拿来把不规范的图像变换为标准形式的图像. 网络 ...

  9. Redis事件通知示例

    1. redis如同zk一样,提供了事件监听(或者说是回调机制), 下面是redis的配置说明: ############################# EVENT NOTIFICATION ## ...

  10. springboot2集成pagehelper

    springboot2集成pagehelper超级简单,本示例直接抄袭官方示例,仅将数据库由H2改成MySQL而已. 1. pom.xml <?xml version="1.0&quo ...