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原理实现表间关联的更多相关文章

  1. mybatis 使用resultMap实现表间关联

    AutoMapping auto mapping,直译过来就是自动映射,工作原理大概如下: 假设我们有一张表,表名为person,包含id,name,age,addr这4个字段 mysql> d ...

  2. MongoDB里做表间关联

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

  3. mybatis笔记3 一些原理的理解

    1,mybatis流程跟踪,原理理解 基本思路: 从SqlSessionFactory的初始化出发,观察资源的准备和环境的准备,以及实现持久层的一些过程: 进入SqlSessionFactoryBea ...

  4. NHibernate系列文章二十八:NHibernate Mapping之Auto Mapping(附程序下载)

    摘要 上一篇文章介绍了Fluent NHibernate基础知识.但是,Fluent NHibernate提供了一种更方便的Mapping方法称为Auto Mapping.只需在代码中定义一些Conv ...

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

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

  6. mybatis plus 一对多,多表联查的使用小记

    阅读本博文需要有基础的mybatis以及mybatis plus知识,如果没有建议您了解相关的内容 本项目使用的是springboot构建的,数据库字段命名不严谨仅做演示测试使用,本文不做相关源码的解 ...

  7. Speed-BI 多事实表与表间计算的应用:销售目标达成分析 另一种实现方法

    在前一篇<Speed-BI多事实表与表间计算的应用(excel多Sheet关联分析):销售目标达成分析>http://www.powerbibbs.com/forum. ... 7583& ...

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

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

  9. mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱

    ​ mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱 ​ 前言:使用 mybatis generator 生成表格对应的pojo.dao.mapper,以及对应的example的 ...

随机推荐

  1. Vim设置Tab宽度/替换Tab为空格

    用户配置: 在/home/you/.vimrc中添加以下代码后,重启vim即可实现按TAB产生4个空格:set ts=4  (注:ts是tabstop的缩写,设TAB宽4个空格)set expandt ...

  2. JAVA设计模式——开篇

    设计模式很重要,重要性我就不再复述了.最主要的是,通常我们在写一定量代码后,常用的方法什么的都熟悉后,想再提高代码能力,我找到的最好的方法还是去学习,理解设计模式.不理解设计模式,看一些开源框架和ja ...

  3. 程序员50题(JS版本)(二)

    程序6:用*号输出字母C的图案 console.log(' ****'); console.log(' ***'); console.log(' **'); console.log(' *'); co ...

  4. java-同步控制及不可变设置(只读访问)

    1.还是直接上代码简单了解一下: package com.synchronize.test; import java.util.ArrayList; import java.util.Collecti ...

  5. XSS 漏洞介绍

    概念: XSS 攻击:跨站脚本攻击 (Cross Site Scripting),为不和层叠样式表 (Cascading Style Sheets, CSS) 的缩写混淆.故将跨站脚本攻击缩写为 XS ...

  6. C#的String.Split 分割字符串用法详解的代码

    代码期间,把代码过程经常用的内容做个珍藏,下边代码是关于C#的String.Split 分割字符串用法详解的代码,应该对码农们有些用途. 1) public string[] Split(params ...

  7. C#获得指定目录床架时间、更新时间和最后访问时间等信息的代码

    将做工程过程常用的内容片段备份一次,下面的内容内容是关于C#获得指定目录床架时间.更新时间和最后访问时间等信息的内容,希望能对小伙伴们也有用. using System;using System.IO ...

  8. Android Camera2 预览功能实现

    1. 概述 最近在做一些关于人脸识别的项目,需要用到 Android 相机的预览功能.网上查阅相关资料后,发现 Android 5.0 及以后的版本中,原有的 Camera API 已经被 Camer ...

  9. ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC控制器简介 ASP.NET Core MVC控制器操作简介 ASP.NET Core MVC控制器操作简介返回类型简介 ASP.NET C ...

  10. UE4分支的Git Flow

    UE4作为开源商业引擎,其代码托管在私有库:https://github.com/EpicGames/UnrealEngine 为了能看到并下载UE4的代码,开发者需要有GitHub账号和Unreal ...