AutoMapping

  auto mapping,直译过来就是自动映射,工作原理大概如下:

  假设我们有一张表,表名为person,包含id,name,age,addr这4个字段

mysql> desc person;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
| age | int(2) | NO | | NULL | |
| addr | varchar(30) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+

  

  同时我们会创建一个实体类Person来与这张person表进行对应,此时Person类的属性名称和person表中的字段名称一一对应,不仅是名称对应,数据类型也是一一对应的:

package lixin.gan.pojo;

public class Person {

	private int id;
private String name;
private int age;
private String addr; // 省略了构造方法、setter、getter、toString
}

    

  之后我们会创建PersonMapper.xml这个映射文件:

<?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="lixin.gan.mapper.PersonMapper">
<select id="selectAll" resultType="lixin.gan.pojo.Person">
select * from person
</select>
</mapper>

  注意上面的resultType,这里的resultType已经指明了返回值的类型,于是mybatis在从结果集中取出一条数据后,会将每一行记录的字段名,对应到Person类的同名属性,将字段值赋值给Person类的同名属性。

  此时需要注意:如果从person表中查询数据,取出结果集中的字段名称,和Person类中的属性值对应不上(名称不相同),那么返回的Person类的对象对应的那个属性就会设置为null。举个例子,person表中的name字段,应该auto mapping到Person类的name属性,但如果,Person类中,没有name属性,却有一个name1属性,那么再返回结果的时候,name1属性就会初始为null。

  虽然resultType很方便,可以自动的实现映射,但是,我们往往需要进行自定义的映射,此时就可以使用resultMap了。

使用resultMap实现单表映射

  假设实体类中Person.java的属性更改如下:

package lixin.gan.pojo;

public class Person {

	private int id1;
private String name1;
private int age1;
private String addr1; // 省略了构造方法、setter、getter、toString
}

  

  要想使用mybatis时,person表的字段仍能正确对应到Person类中的准确字段中,使用resultMap来指定对应关系,可以这样做:

<?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="lixin.gan.mapper.PersonMapper"> <!-- 定义数据表中的字段,与实体类中的属性对应关系 -->
<resultMap type="lixin.gan.pojo.Person" id="testResultMap">
<!-- 数据表中的主键列字段使用<id />标签, 其他字段使用<result />标签 -->
<!-- column表示的是数据表中的字段, property表示的是实体类中对应的属性 -->
<id column="id" property="id1" />
<result column="name" property="name1" />
<result column="age" property="age1" />
<result column="addr" property="addr1" />
</resultMap> <!-- 此时不用resultType属性,而是使用resultMap属性,属性值就是前面定义的对应关系id -->
<select id="selectAll" resultMap="testResultMap">
select * from person
</select>
</mapper>

  

使用resultMap实现n+1查询

  n+1查询是指:先查询出某个表的全部信息,然后根据这个表的信息,去查询另外一个表的信息。

  举下面一个例子:查询student表后,根据student表中的tid,查询对应的teacher表中信息。

  Teacher类(对应teacher表),实体类定义如下:

package lixin.gan.pojo;

public class Teacher {
private int id;
private String name; // 省略了构造方法、setter、getter、toString
}

  

  TeacherMapper.xml中的内容如下:

<?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="lixin.gan.mapper.TeacherMapper"> <resultMap type="lixin.gan.pojo.Teacher" id="teacherMap">
<id column="id" property="id" />
<result column="name" property="name" />
</resultMap> <select id="selectAllTeacher" resultMap="teacherMap">
select * from teacher
</select> <select id="selectTeacherById" resultType="teacher" parameterType="int">
select * from teacher where id=#{0}
</select>
</mapper>

  

  现在有一个Student类(对应student表),实体类定义如下:

package lixin.gan.pojo;

public class Student {
private int id; // 学生id
private int age; // 学生年龄
private String name;// 学生姓名
private int tid; // 老师的id
private Teacher teacher; // 包含一个Teacher对象
// 省略了构造方法、setter、getter、toString
}

  与此同时,StudentMapper.xml中的内容如下:

<?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="lixin.gan.mapper.StudentMapper"> <!-- 定义数据表中的字段,与实体类中的属性对应关系 -->
<resultMap type="lixin.gan.pojo.Student" id="studentMap">
<id column="id" property="id" /> <result column="name" property="name" />
<result column="age" property="age" />
<result column="tid" property="tid" /> <!-- 如果当前xml对应的实体类中包含一个类对象,那么可以使用association标签来进行关联 -->
<!-- property仍旧指的是实体类中的属性名,select表示要为该属性赋值,需要执行的查询操作(id),column表示传入的参数-->
<association
property="teacher"
select="lixin.gan.mapper.TeacherMapper.selectTeacherById"
column="tid"
></association> <!-- 如果当前的xml对应的实体来中包含一个容器集合,那么可以使用collection标签来进行关联 -->
<!-- <collection property=""></collection> -->
</resultMap> <select id="selectAllStudent" resultMap="studentMap">
select * from student
</select>
</mapper>

  

  测试代码:

package lixin.gan.test;

import java.io.InputStream;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import lixin.gan.pojo.Student; public class Test {
public static void main(String[] args) throws Exception{
InputStream config = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config); SqlSession session = factory.openSession(); List<Student> list = session.selectList("lixin.gan.mapper.StudentMapper.selectAllStudent"); for (Student stu : list) {
System.out.println(stu);
}
}
}

  运行结果,打印log4j日志:

==>  Preparing: select * from student
==> Parameters:
====> Preparing: select * from teacher where id=?
====> Parameters: 2(Integer)
<==== Total: 1
====> Preparing: select * from teacher where id=?
====> Parameters: 1(Integer)
<==== Total: 1
====> Preparing: select * from teacher where id=?
====> Parameters: 5(Integer)
<==== Total: 1
====> Preparing: select * from teacher where id=?
====> Parameters: 4(Integer)
<==== Total: 1
<== Total: 4
Student [id=1, age=5, name=张三, tid=2, teacher=Teacher [id=2, name=黄老师]]
Student [id=2, age=10, name=李四, tid=1, teacher=Teacher [id=1, name=李老师]]
Student [id=3, age=25, name=王五, tid=5, teacher=Teacher [id=5, name=方老师]]
Student [id=4, age=30, name=赵六, tid=4, teacher=Teacher [id=4, name=蔡老师]]

  

使用resultMap关联集合对象

  关联集合对象,可以理解为,一个类A的某个属性,是包含另一个类B的集合。

  举例:一个老师有多个学生,查询所有老师,并且查出老师的学生。

  Student.java实体类如下:

package lixin.gan.pojo;

public class Student {
private int id; // 学生id
private int age; // 学生年龄
private String name;// 学生姓名
private int tid; // 老师的id // 省略了构造方法,setter、getter、toString
}

  对应的StudentMapper.xml为:

<?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="lixin.gan.mapper.StudentMapper">
<select id="selectStudentById" resultType="lixin.gan.pojo.Student">
select * from student where tid=#{0}
</select>
</mapper>

  

  Teacher.java实体类内容如下:

package lixin.gan.pojo;

import java.util.List;

public class Teacher {
private int id;
private String name; private List<Student> list; // 省略了构造方法,setter、getter、toString
}

  TeacherMapper.xml对应的内容如下:

<?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="lixin.gan.mapper.TeacherMapper"> <resultMap type="lixin.gan.pojo.Teacher" id="teacherMap">
<id column="id" property="id" />
<result column="name" property="name" /> <!-- 当关联的类型是集合类型,那么就需要使用collection标签,并且要指定ofType,表示集合中元素的值 -->
<collection
property="list"
select="lixin.gan.mapper.StudentMapper.selectStudentById"
ofType="lixin.gan.pojo.Student"
column="id"
></collection>
</resultMap> <select id="selectAllTeacher" resultMap="teacherMap">
select * from teacher
</select> </mapper>

  

  运行测试代码:

package lixin.gan.test;

import java.io.InputStream;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import lixin.gan.pojo.Teacher; public class Test {
public static void main(String[] args) throws Exception{
InputStream config = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config); SqlSession session = factory.openSession(); List<Teacher> list = session.selectList("lixin.gan.mapper.TeacherMapper.selectAllTeacher"); for (Teacher teacher : list) {
System.out.println(teacher);
}
}
}

  

  利用log4j打印的日志,以及程序运行输出如下:

==>  Preparing: select * from teacher
==> Parameters:
====> Preparing: select * from student where tid=?
====> Parameters: 1(Integer)
<==== Total: 1
====> Preparing: select * from student where tid=?
====> Parameters: 2(Integer)
<==== Total: 3
====> Preparing: select * from student where tid=?
====> Parameters: 3(Integer)
<==== Total: 0
====> Preparing: select * from student where tid=?
====> Parameters: 4(Integer)
<==== Total: 2
====> Preparing: select * from student where tid=?
====> Parameters: 5(Integer)
<==== Total: 1
<== Total: 5
Teacher [id=1, name=李老师, list=[Student [id=2, age=10, name=李四, tid=1]]]
Teacher [id=2, name=黄老师, list=[Student [id=1, age=5, name=张三, tid=2], Student [id=5, age=22, name=小红, tid=2], Student [id=6, age=23, name=小花, tid=2]]]
Teacher [id=3, name=王老师, list=[]]
Teacher [id=4, name=蔡老师, list=[Student [id=4, age=30, name=赵六, tid=4], Student [id=7, age=30, name=小黄, tid=4]]]
Teacher [id=5, name=方老师, list=[Student [id=3, age=25, name=王五, tid=5]]]

  

  

mybatis 使用resultMap实现表间关联的更多相关文章

  1. mybatis 使用auto mapping原理实现表间关联

    Auto mapping的示例 数据库中有一个person表,结构如下: mysql> desc person; +-------+-------------+------+-----+---- ...

  2. MongoDB里做表间关联

    MongoDB与关系型数据库的建模还是有许多不同,因为MongoDB支持内嵌对象和数组类型.MongoDB建模有两种方式,一种是内嵌(Embed),另一种是连接(Link).那么何时Embed何时Li ...

  3. Mybatis框架学习总结-表的关联查询

    一对一关联 创建表和数据:创建一张教师表和班级表,这里假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关系. CREATE TABLE teacher( t_id INT PRIM ...

  4. MyBatis学习(二)---数据表之间关联

    想要了解MyBatis基础的朋友可以通过传送门: MyBatis学习(一)---配置文件,Mapper接口和动态SQL http://www.cnblogs.com/ghq120/p/8322302. ...

  5. 【Mybatis】MyBatis之表的关联查询(五)

    本章介绍Mybatis之表的关联查询 一对一关联 查询员工信息以及员工的部门信息 1.准备表employee员工表,department部门表 CREATE TABLE `employee` ( `i ...

  6. MyBatis入门程序之表关联

    一.一对一查询(ResultType比较简单,只需要指向扩展的类:ResultMap逐个匹配比较麻烦,可以配置属性autoMapping="true",还可以可以实现延迟加载) 1 ...

  7. mysql 常用命令 | 表间 弱关联 join

    show databases; use mhxy; select database(); show tables; desc account_list_175; ),(); select from_u ...

  8. Mybatis中的多表查询 多对多

    示例:用户和角色 一个用户可以有多个角色 一个角色可以赋予多个用户 步骤: 1.建立两张表:用户表,角色表 让用户表和角色表具有多对多的关系. 需要使用中间表,中间表中包含各自的主键,在中间表中是外键 ...

  9. Mybatis的ResultMap的使用

    本篇文章通过一个实际工作中遇到的例子开始吧: 工程使用Spring+Mybatis+Mysql开发.具体的业务逻辑很重,对象之间一层一层的嵌套.和数据库表对应的是大量的model类,而和前端交互的是V ...

随机推荐

  1. Html5 localStorage 缓存

    1.客户端页面临时存贮数据变化多段,cookie ,session, data-xxx , hidden input 这些司空见惯不废话,我们采用 localStorage 特点:1.数据不会删除,除 ...

  2. Android破解学习之路(十一)—— 关于去更新

    根据对话框的文字找到对应的对话框,设置visability 为gone 修改版本号,aptool 搜索http://,找到更新的地址,修改为127.0.0.0 搜索update,upgrade,ver ...

  3. C++系列总结——构造与析构

    前言 在使用资源前,我们需要做一些准备工作保证资源能正常使用,在使用完资源后,我们需要做一些扫尾工作保证资源没有泄露,这就是构造与析构了,这和编程语言是无关的,而是使用资源的一种方式.C++只不过是把 ...

  4. 20190328-CSS样式一:字体样式font-、文本样式text-、背景图样式background-

    目录 CSS参考手册:http://css.doyoe.com/ 1.字体简写:font:font-style || font-variant || font-weight || font-size ...

  5. 博弈论进阶之Multi-SG

    Multi-Nim 从最简单的Nim模型开始 它的定义是这样的 有\(n\)堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿)或把一堆数量不少于\(2\)石子分为两堆不为空的石子,没法拿的人 ...

  6. 虚拟主机、VPS主机与云服务器的区别

    本文转载自星光云 http://www.365yun.top/news/list.asp?newsid=22 虚拟主机是利用虚拟技术将一台物理服务器划分成多个“虚拟”服务器,虚拟主机的出现大大节省了服 ...

  7. LEDAPS1.3.0版本移植到windows平台----HuCsm云掩膜模块

    这个是2012年左右放在百度空间的,谁知百度空间关闭...转移到博客园. 最近项目用到3.1.2版本的LEDAPS,新版本的使用情况会在后续文章中慢慢丰富. HuCsm是将LEDAPS项目中的TM/E ...

  8. 关于JPasswordField的getText()方法过时问题解决

    这几天想做一个登陆界面,用Jframe做,连接数据库时发现JPasswordField的getText()过时了,没法使用.查了资料发现改成了: try{ String sql="SELEC ...

  9. (办公)SpringBoot与mybatisGenerator自动生成.

    20181206-自动生成,少写一点代码. (以下的内容主要参考csdn上的<[完美]SpringBoot+Mybatis-Generator自动生成>这篇文章,还有简书上的mbatis- ...

  10. DVWA 黑客攻防演练(六)不安全的验证码 Insecure CAPTCHA

    之前在 CSRF 攻击 的那篇文章的最后,我觉得可以用验证码提高攻击的难度. 若有验证码的话,就比较难被攻击者利用 XSS 漏洞进行的 CSRF 攻击了,因为要识别验证码起码要调用api,跨域会被浏览 ...