mybatis 使用auto mapping原理实现表间关联
Auto mapping的示例
数据库中有一个person表,结构如下:
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表中的字段名一一对应。
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="selectAllPerson" resultType="lixin.gan.pojo.Person" >
select * from person
</select> </mapper>
在调用lixin.gan.mapper.PersonMapper.selectAllPerson方法时,返回结果集中,每一条数据,都对应到一个Person类对象,应该将person表中字段值对应到Person对象的同名属性中,于是,我们在测试的时候,获得的结果就是这样的:
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.Person; 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<Person> list = session.selectList("lixin.gan.mapper.PersonMapper.selectAllPerson"); for (Person p : list) {
System.out.println(p);
} session.close();
}
}
运行结果如下:
==> Preparing: select * from person
==> Parameters:
<== Total: 4
Person [id=1, name=张三, age=30, addr=北京]
Person [id=2, name=李四, age=40, addr=上海]
Person [id=3, name=王五, age=20, addr=广州]
Person [id=4, name=赵六, age=35, addr=深圳]
现在如果将Person类中的name属性更改为name1,age更改为age1,那么再次运行测试代码:
package lixin.gan.pojo; public class Person {
private int id;
private String name1;
private int age1;
private String addr; //省略了构造方法,setter、getter、toString
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}
public int getAge1() {
return age1;
}
public void setAge1(int age1) {
this.age1 = age1;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
运行结果:
==> Preparing: select * from person
==> Parameters:
<== Total: 4
Person [id=1, name1=null, age1=0, addr=北京]
Person [id=2, name1=null, age1=0, addr=上海]
Person [id=3, name1=null, age1=0, addr=广州]
Person [id=4, name1=null, age1=0, addr=深圳]
可以看到,上面的name1属性和age1属性,并没有被赋值。
这里有一点很重要:mybatis在为对象属性赋值的时候,其实并不是将查出来的字段值,直接赋值给对象的同名属性,而是调用setter方法进行赋值。假设name属性会调用setName来将name字段值赋值给对象中与name字段对应的属性,这个属性可能是name,也可能是name1,上面这个Person中的name1,利用IDE生成的setter方法名称是setName1,可以调用setName1()对name1属性进行赋值,但是因为name字段没有找到对应的setName方法,所以对象中的name1属性就没有赋值。
示例:
package lixin.gan.pojo; public class Person {
private int id;
private String name1;
private int age1;
private String addr; //省略了构造方法,setter、getter、toString public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name1;
}
public void setName(String name1) {
this.name1 = name1;
}
public int getAge() {
return age1;
}
public void setAge(int age1) {
this.age1 = age1;
}
}
注意上面的name1属性,使用setName()为name1进行赋值,使用setAge()为age1属性进行赋值。所以,运行测试的时候,输出的内容如下;
==> Preparing: select * from person
==> Parameters:
<== Total: 4
Person [id=1, name1=张三, age1=30, addr=北京]
Person [id=2, name1=李四, age1=40, addr=上海]
Person [id=3, name1=王五, age1=20, addr=广州]
Person [id=4, name1=赵六, age1=35, addr=深圳]
同样的,在mapper.xml中,如果传入的参数是一个对象,可以使用#{field}获取对象的field属性值,调用的是getter方法,而不是直接使用的属性值。
类间的包含的auto mapping
举个例子,有两个表,husband表和wife表。
表结构如下:
mysql> desc wife;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+ mysql> desc husband;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
| wid | int(11) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
对应的Wife.java和Husband.java中是两个表中对应的实体类。
package lixin.gan.pojo; public class Wife {
private int id;
private String name; // 省略了构造方法,setter、getter、toString
}
package lixin.gan.pojo; public class Husband {
private int id;
private String name;
private int wid; //wife的id
private Wife wife; //包含一个Wife对象 // 省略了构造方法,setter、getter、toStrin
}
如果要查出husband表中的所有数据,并且联合wife表,查出wife信息。
现在看一下HusbandMapper.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.HusbandMapper">
<select id="selectAll" resultType="lixin.gan.pojo.Husband" >
select * from husband left join wife on husband.wid=wife.id
</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.Husband; 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<Husband> list = session.selectList("lixin.gan.mapper.HusbandMapper.selectAll"); for (Husband p : list) {
System.out.println(p);
} session.close();
}
}
输出内容如下(包含log4j日志):
==> Preparing: select * from husband left join wife on husband.wid=wife.id
==> Parameters:
<== Total: 4
Husband [id=1, name=小黄, wid=2, wife=null]
Husband [id=2, name=小凯, wid=4, wife=null]
Husband [id=3, name=小亮, wid=1, wife=null]
Husband [id=4, name=小辉, wid=3, wife=null]
上面的运行结果,很容易就发笑,wife属性(Wife类的对象)值为null,这是因为没有进行赋值,这是为什么呢?这个还得看一下我们的HusbandMapper.xml中写的那一条sql语句。
select * from husband left join wife on husband.wid=wife.id
上面这个查询之后,结果集中包含这么几个字段:
Database changed
mysql> select * from husband left join wife on husband.wid=wife.id;
+----+--------+-----+------+--------+
| id | name | wid | id | name |
+----+--------+-----+------+--------+
可以从查询结果中,看到,重复的id和name字段,并且,后面的那个id和name字段本应该赋值给Husband类的wife属性,而wife属性本来就是一个对象。
使用别名来解决问题
在mysql中,select的字段后面使用as或者空格分隔,之后跟的一个名称就是该字段的别名,在返回的时候,返回别名即可。
上面的husband类中包含一个wife的对象属性,wife属性(对象)又包括id、name,所以,mybatis中的sql语句,使用别名时,使用wife.id和wife.name即可为wife属性赋值。
修改HusbandMapper.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.HusbandMapper">
<select id="selectAll" resultType="lixin.gan.pojo.Husband" >
select husband.id `id`, husband.name `name`, husband.wid `wid`,
wife.id `wife.id`, wife.name `wife.name`
from husband left join wife on husband.wid=wife.id
</select>
</mapper>
运行测试:
==> Preparing: select husband.id `id`, husband.name `name`,
husband.wid `wid`, wife.id `wife.id`, wife.name `wife.name` from husband
left join wife on husband.wid=wife.id
==> Parameters:
<== Total: 4
Husband [id=1, name=小黄, wid=2, wife=Wife [id=2, name=小红]]
Husband [id=2, name=小凯, wid=4, wife=Wife [id=4, name=小云]]
Husband [id=3, name=小亮, wid=1, wife=Wife [id=1, name=小花]]
Husband [id=4, name=小辉, wid=3, wife=Wife [id=3, name=小娇]]
auto mapping不能解决的问题
仍旧使用上面的例子,auto-mapping就不能解决一夫多妻的问题,一个husband对象中,有一个属性是List,每一个List的元素是wife对象。
这个问题可以使用resultMap来解决问题。
可以参考:mybatis 使用resultMap实现表间关联
mybatis 使用auto mapping原理实现表间关联的更多相关文章
- mybatis 使用resultMap实现表间关联
AutoMapping auto mapping,直译过来就是自动映射,工作原理大概如下: 假设我们有一张表,表名为person,包含id,name,age,addr这4个字段 mysql> d ...
- MongoDB里做表间关联
MongoDB与关系型数据库的建模还是有许多不同,因为MongoDB支持内嵌对象和数组类型.MongoDB建模有两种方式,一种是内嵌(Embed),另一种是连接(Link).那么何时Embed何时Li ...
- mybatis笔记3 一些原理的理解
1,mybatis流程跟踪,原理理解 基本思路: 从SqlSessionFactory的初始化出发,观察资源的准备和环境的准备,以及实现持久层的一些过程: 进入SqlSessionFactoryBea ...
- NHibernate系列文章二十八:NHibernate Mapping之Auto Mapping(附程序下载)
摘要 上一篇文章介绍了Fluent NHibernate基础知识.但是,Fluent NHibernate提供了一种更方便的Mapping方法称为Auto Mapping.只需在代码中定义一些Conv ...
- mysql 常用命令 | 表间 弱关联 join
show databases; use mhxy; select database(); show tables; desc account_list_175; ),(); select from_u ...
- mybatis plus 一对多,多表联查的使用小记
阅读本博文需要有基础的mybatis以及mybatis plus知识,如果没有建议您了解相关的内容 本项目使用的是springboot构建的,数据库字段命名不严谨仅做演示测试使用,本文不做相关源码的解 ...
- Speed-BI 多事实表与表间计算的应用:销售目标达成分析 另一种实现方法
在前一篇<Speed-BI多事实表与表间计算的应用(excel多Sheet关联分析):销售目标达成分析>http://www.powerbibbs.com/forum. ... 7583& ...
- 【Mybatis】MyBatis之表的关联查询(五)
本章介绍Mybatis之表的关联查询 一对一关联 查询员工信息以及员工的部门信息 1.准备表employee员工表,department部门表 CREATE TABLE `employee` ( `i ...
- mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱
mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱 前言:使用 mybatis generator 生成表格对应的pojo.dao.mapper,以及对应的example的 ...
随机推荐
- MySQL 笔记整理(8.b) --事务到底是隔离还是不隔离的?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 8.a) --事务到底是隔离还是不隔离的? 本周工作较忙,加上懒惰,拖更 ...
- java_泛型2
一.泛型_泛型概述及好处 1).在定义集合时,我们是希望集合中只存储一种类型的引用,这时可以使用泛型: ArrayList<String> list = new Arr ...
- 一文读懂HTTP/2及HTTP/3特性
摘要: 学习 HTTP/2 与 HTTP/3. 前言 HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何 ...
- Vue中父组件传子组件
父组件代码: <template> <section :class="menuMode === 'vertical' ? 'vertical-sub-nav' : 'sub ...
- 51nod“省选”模测第二场 C 小朋友的笑话(线段树 set)
题意 题目链接 Sol 直接拿set维护\(li\)连续段.因为set内的区间互不相交,而且每个线段会被至多加入删除一次,所以复杂度是对的. #include<bits/stdc++.h> ...
- 【Dojo 1.x】笔记1 入门
Dojo是个框架 ,是个js框架,现在除了这一点什么都不知道,就这么上手了. ps:不建议Web初学者看我的笔记,这个要有一定积累才能看. 在<body>标签内写这么一点代码: <b ...
- Android入门第一课之Java基础
通知:由于本周六场地申请没通过,所以本周的培训临时取消. 今天给大家带来的是Android入门的第一课,由于教室申请的不确定性,因此,每次培训的内容都会在博客先提前释放出来.首先Android的APP ...
- 南京邮电大学 JavaA期末复习要点总结
南京邮电大学 JavaA复习要点: Chap1 入门 1. Java应用程序开发过程教材P14~P15 Chap 2 基本语法 1. 标识符的命名规则教材P19 字母下划线美元符号开头,除 ...
- webpack安装、基本配置
文章结构: 什么是webpack? 安装webpack webpack基本配置 一.什么是webpack? 在学习react时发现大部分文章都是react和webpack结合使用的,所以在学react ...
- MySQL之Innodb恢复的学习笔记
MySQL · 引擎特性 · InnoDB 崩溃恢复过程 enum { SRV_FORCE_IGNORE_CORRUPT = 1, /*!< let the server run even if ...