Mybatis sql映射文件浅析 Mybatis简介(三) 简介

时间:2023-03-08 23:54:38
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

Mybatis sql映射文件浅析 Mybatis简介(三)

简介
除了配置相关之外,另一个核心就是SQL映射,MyBatis 的真正强大也在于它的映射语句。
Mybatis创建了一套规则以XML为载体映射SQL
之前提到过,各项配置信息将Mybatis应用的整体框架搭建起来,而映射部分则是准备了一次SQL操作所需的信息
一次SQL执行的主要事件是什么?
输入参数解析,绝大多数SQL都是需要参数的
SQL,通过SQL与数据库交互,所以最根本的是SQL,如果连SQL都没有,还扯个蛋蛋?
结果映射,Mybatis可以帮我们完成字段与Java类型的映射
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
所以说SQL映射的核心内容为:
  • SQL内容指定
  • 参数信息设置
  • 输出结果设置
当然,每个SQL都需要指定一个ID作为用于执行时的唯一标识符
比如下面示例
<select id="selectPerson"parameterType="int"resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
SELECT * FROM PERSON WHERE ID = #{id}  为SQL内容部分
parameterType="int" 以及SQL中的#{id}为参数信息设置部分
resultType="hashmap" 为输出结果设置部分

概况

如上所述,核心内容为:
  • ID
  • SQL内容
  • 入参设置
  • 结果配置
ID用于执行时唯一定位一个映射
对于SQL内容,也没有什么特别的,就是平常所说的数据库可以执行的SQL语句
对于SQL内容中的参数,MyBatis 会通过 JDBC创建一个预处理语句参数
这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中,类似这样:
// Similar JDBC code, NOT MyBatis…String selectPerson ="SELECT * FROM PERSON WHERE ID=?";PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
输入的类型使用parameterType进行指定(parameterMap – 已废弃!)
输出信息使用resultMap或者resultType进行指定
从包含的信息的角度分析Mybatis 映射文件的核心内容
如下图所示:
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
而对于数据库的CRUD操作,Mybatis的XML配置中分别使用了 insert、select、update、delete四个标签进行分别处理
所以一个映射(映射文件中的一个)常见的形式如下,parameterType以及resultType | resultMap 会根据SQL的类型需要或者不需要
<select | insert | update | delete  id="......"       parameterType="......"    resultType | resultMap="......">
SQL内容......
</select | insert | update | delete>
核心信息为通过Mybatis执行一次SQL的必备信息,Mybatis还可以提供更多的功能设置
所以对于不同类型的SQL,还会有更多的一些配置条目
比如之前提到过的数据库厂商标识符 databaseId,所有类型的SQL映射都可以设置这一属性
而对于其他的附加辅助属性配置,有些是所有类型共同的,而有些是特有的
databaseId就是共有的,比如用于返回自动生成的键的配置useGeneratedKeys 只有insert与update才拥有

文档结构解析

所以从文档结构的形式角度看SQL映射,有四种类型的映射 select、insert、update、delete 
每种类型又都有各自的属性设置,有一些是共同的,有一些是特有的
下图如果不清楚,请到评论区中,右键,新标签查看图片,可以查看到大图
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

属性角度解析

如果从属性的角度去看待各自的归属,每种属性都有各自的作用功能
他们自身的功能也决定了那些类型才能拥有他
比如键值的返回相关的useGeneratedKeys,就只可能发生在insert或者update中,只有他们才可能自动生成键
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
以上为SQL映射文件的核心关键信息以及属性的解读
有些细节还需要注意,关于flushCache以及userCache,前者是是否清空清空本地缓存和二级缓存,后者是本条语句的结果是否进行二级缓存,含义完全不一样
四种类型都有flushCache属性,对于select默认false,对于insert、update、delete默认是true
而userCache只有select有,默认是true
因为缓存机制,比如update 的时候如果 设置flushCache="false",则当你更新后,查询的数据数据还是老的数据。

额外的馈赠-语法糖

在编程实践中,经常有一些公共的方法或者处理逻辑,我们通常将他们提取单独封装,以便提高代码复用程序
那么,对于SQL的编写呢?
Mybatis也提供了封装提取的手段---SQL元素标签
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<sql id="xxx">

........

</sql>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
然后可以使用include,将他包含到指定的位置
<include refid="xxx"></include>
这是一种静态的织入,通过SQL元素,你可以方便的完成公共SQL片段的提取封装
如果有两个表,都有name、age等字段,我想将他们封装,但是表名却又不一样怎么办?
SQL元素还提供了别名的设置,可以很容易的解决这个问题,请参考官方文档
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
这个 SQL 片段可以被包含在其他语句中,例如:
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<select id="selectUsers"resultType="map">
select
<include refid="userColumns"><propertyname="alias"value="t1"/></include>,
<include refid="userColumns"><propertyname="alias"value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
上面示例中包含了两次SQL片段,第一次中alias被替换为t1 ,第二次中的alias被替换为t2,最终的结果形式为:
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
select
t1.id,
t1.username,
t1.password,
t2.id,
t2.username,
t2.password
from
some_table t1
cross join some_table t2
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

深入映射

参数(Parameters)细节配置

<selectid="selectPerson"parameterType="int"resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
示例中入参类型通过parameterType指定为int,参数占位符为#{id},这是最简单的一种形式了,入参只是一个Java基本类型(非自定义的对象类型)
对于对象类型Mybatis也可以很好的完成工作,不管是入参时的解析,还是输出结果的映射解析
能够根据属性的名称进行自动的配对
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<select id="selectUsers"resultType="User">
select id, username, password
from users
where id = #{id}
</select>
<insert id="insertUser"parameterType="User">
insert into users (id, username, password)
values (#{id}, #{username}, #{password})
</insert>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
不仅仅支持对象,而且还支持map,当parameterType="map"时,map的key会被用来和占位符中的名称进行匹配
也就是说对于: SELECT * FROM PERSON WHERE ID = #{id}    ,当parameterType="map"时,你的参数map需要存在  key=id  的元素
parameterType也支持list,当parameterType="list"时,可以借助于动态SQL的foreach 进行循环
如果是基本数据类型的List,比如List<Integer> 那么直接循环即可;如果是List<User>,可以通过遍历每个元素,然后通过#{item.username}、#{item.password}的形式进行读取
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<insert id="..." parameterType="List">
INSERT INTO xxx_table(
username,
password,
createTime
)
values
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.username},
#{item.password},
#{item.createTime}
)
</foreach>
</insert>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

 

可以看得出来,类型的形式很丰富,Mybatis很多时候都可以自动处理,但是你可以对他进行显式的明确指明,比如
#{property,javaType=int,jdbcType=NUMERIC}
property表示字段名称,javaType为int,jdbcType为NUMERIC
(jdbcType是JDBC对于数据库类型的抽象定义,详见java.sql.JDBCType 或者java.sql.Types,可以简单认为数据库字段类型
javaType 通常可以由参数对象确定,除非该对象是一个 HashMap,是map的时候通常也可以很好的工作,但是建议在入参类型是Map对他进行明确的指定
需要注意的是:如果一个列允许 null 值,并且会传递值 null 的参数,就必须要指定 JDBC Type
当你在插入时,如果需要使用自定义的typeHandler ,也应该在此处进行指定
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
对于数值类型,还可以设置保留小数的位数
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
对于参数的细化配置也很容易理解,他要么是用于使用时确定入参或者数据库字段的具体类型,如javaType或者jdbcType
要么就是在字段处理过程中增加的一些处理所需要的信息,比如是不是需要按照自定义处理器处理后在执行到数据库?是不是将数值的小数位数处理后在去执行数据库?
另外对于存储过程的调用Mybatis也是有支持的,mode 属性允许你指定 IN,OUT 或 INOUT 参数。
通常我们使用#{}的格式进行字符串处理,这样可以安全,是通常的首选,但是如果你就是想直接插入一个字符串到SQL中,可以使用,不过很显然,,不过很显然,的使用你要非常慎重

ResultMap-别名映射

Mybatis好用的一大神器就是ResultMap,可以让你高效灵活的从结果集映射到你想要的类型中,能够进行很多高级的映射
 一般的映射可以借助于resultType就可以解决了,resultType后面的值同parameterType类似
parameterType  resultType的值都用于明确类型,可以使用完全限定名
不过你是否还记得入门简介中关于typeAlias中的介绍?
Mybatis内置了Java基础类型的别名,你都可以直接使用
借助于resultType可以完成一些基本的诉求,比如从单表到对应实体类对象的映射,能够自动的根据字段名称和属性名称进行匹配
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
但是如果名称不对应又该怎么办?
如果你的实体中的属性名称为userName,数据库字段名为name,Mybatis真的敢擅自的将这两者对应起来么?
如下图所示,将之前的第一个示例稍作修改,增加一个StudentAnother,name更改为了userName,并将测试代码稍作修改
从结果可以看得到,实体中的userName是null ,Mybatis肯定不敢擅自映射
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
一种可行的方式是使用别名,通过数据库字段AS设置别名,就可以成功的完成映射
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
通过别名,将数据库列名通过别名与属性字段建立映射关系,然后Mybatis就可以进行自动匹配了
但是这种形式如果有多条SQL,每个SQL中都需要有别名,而且,如果后续有原因修改对象的字段名字,怎么办?
另外的方式就是使用ResultMap,ResultMap的基础用法就是相当于设置别名
但是借助于ResultMap,将别名的映射关系,维护在ResultMap中,所有使用到此映射类型的SQL都只需要关联这个ResultMap即可,如果有变更,仅仅需要变更ResultMap中的属性字段对应关系
所有的SQL中的内容并不需要变动
如下图所示,SQL中字段与实体类中不匹配,查询的结果为null
右侧通过ResultMap将userName与列名name进行了映射,就可以成功读取数据
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
ResultMap最基础的形式如下
<resultMap id="............" type=".................">
<id property="............" column="............"/>
<result property="............" column="............"/>
</resultMap>
ResultMap需要id和type,id用于唯一标识符,type用于指明类型,比如Blog
ResultMap最基础的两个信息是id和result元素
他们的内容均为property="......." column="...........",property(对象的属性字段)和clumn(数据库的列名)
对于基础性的映射借助于id和result就可以完全搞定, id 表示的结果将是对象的标识属性,可以认为对象的唯一标识符用id指定,这对于性能的提高很有作用

小结

对于ResultMap就是做字段到属性的映射,id和result都是这个作用,但是如果是唯一标识符请使用id来指定

另外对于每一个字段,还可以明确的声明javaType和jdbcType,以及typeHandler用于更加细致的解析映射
所以说基本元素为:
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

ResultMap-高级映射

ResultMap当然不仅仅是像上面那样只是别名的转换,还可以进行更加复杂的映射
对于结果集返回有哪些场景?
“将一行记录映射为一个对象”与“将多行记录映射为对象列表”这两者本质是一样的,因为所需要做的映射是一样的
比如上面数据库列名name到字段userName 的映射,不管是一行记录还是多行记录,他们都是一样的
所以下面就以一个对象为例
单纯的映射
比如上面的例子,数据库列名与实体类中的字段一一对应(尽管名称不完全匹配,但是仍旧是一一对应的)
组合的映射
对于关系型数据库存在着关联关系的说法,一对一,一对多等
这些关联关系最终也是要映射到对象中的, 所以对象中经常也会存在多种对应关系
比如下面官方文档中的示例----查询博客详情 
一个博客Blog 对应着一个作者Author ,一个作者可能有多个博文Post,每篇博文有零或多条的评论Post_Tag 和标签Tag
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<!-- Very Complex Statement -->
<selectid="selectBlogDetails"resultMap="detailedBlogResultMap">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio,
A.favourite_section as author_favourite_section,
P.id as post_id,
P.blog_id as post_blog_id,
P.author_id as post_author_id,
P.created_on as post_created_on,
P.section as post_section,
P.subject as post_subject,
P.draft as draft,
P.body as post_body,
C.id as comment_id,
C.post_id as comment_post_id,
C.name as comment_name,
C.comment as comment_text,
T.id as tag_id,
T.name as tag_name
from Blog B
left outer join Author A on B.author_id = A.id
left outer join Post P on B.id = P.blog_id
left outer join Comment C on P.id = C.post_id
left outer join Post_Tag PT on PT.post_id = P.id
left outer join Tag T on PT.tag_id = T.id
where B.id = #{id}
</select>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
对于实体类,一种可能的形式如下
Blog中有一个Author,有一个List<Post> ,每一个Post中又有List<Comment> 和  List<Tag>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
可以看得出来对于组合映射又有一对一以及一对多两种形式
(尽管Blog存在List<Post> postList; 但是在Mybatis中使用时,对于关系是从紧邻的上一层确定的,比如对于Comment看Post,对于Post看Blog,而不是从Blog看Comment  )
Mybatis的ResultMap可以完成类似上述SQL与实体类的映射
在Mybatis中只有两种情况,一对一和一对多

一对一Association

对于一对一被称作关联,在ResultMap中使用association元素表示这种关系 
含义为:
association中的所有的字段 映射为association元素上property指定的一个属性
比如下面示例,将id和username 映射为author,谁的author?他的直接外层是谁就是谁!
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<association property="author"column="blog_author_id"javaType="Author">
<id property="id"column="author_id"/>
<result property="username"column="author_username"/> </association>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
对于association的基本格式如下,相当于在基础的ResultMap中插入了一个“一对一”的对应
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<resultMap id="............" type=".................">
<id property="............" column="............"/>
<result property="............" column="............"/>
<association property="............" column="............" javaType="............">
<id property="............" column="............"/>
<result property="............" column="............"/> </association> </resultMap>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
association中对于字段和属性的映射也是使用id和result,对于唯一标志使用id来表示

关联的嵌套查询

对于一个association还可以对他进行嵌套查询,也就是在查询中进行查询
比如官方示例中
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<resultMap id="blogResult"type="Blog">
<association property="author"column="author_id"javaType="Author"select="selectAuthor"/>
</resultMap> <select id="selectBlog"resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select> <selectid="selectAuthor"resultType="Author">
SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
当执行selectBlog时,会执行 SELECT * FROM BLOG WHERE ID = #{id}  ,查询得到的结果映射到blogResult,在这个ResultMap中使用了association元素
这个association元素使用select标签进行了嵌套查询,也就是使用另外的一个映射selectAuthor进行处理
处理流程:
  1. 先查询selectBlog查询所有的结果
  2. 对于每一条结果,然后又再一次的select,这就是嵌套查询
这会出现“N+1 查询问题”,查询一次SQL查询出一个列表(这是1)然后对于这个列表的每一个结果都再次的查询(这是N)性能有些时候很不好
嵌套查询使用select,还有一个重要的就是association 上的 column,这个column用于指定嵌套查询的参数
比如上面的例子,将会使用author_id传递给 SELECT * FROM AUTHOR WHERE ID = #{id}中的id,然后进行查询
此处仅仅只是一个参数,如果是多个参数仍旧可以,使用 column= ” {prop1=col1,prop2=col2} ”的形式
比如:
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
上面就是通过column指定将要传递给嵌套内查询的参数
鉴于ResultMap可以提供很好地映射,所以上面的示例完全可以修改为普通的association形式,通过join将关联查询的结果映射到指定的对象中,而不是借助于select元素进行嵌套查询

一对多collection

对于一对多关系,Mybatis使用collection
collection的逻辑本质上与association是一样的,都是对象字段映射
只不过用于区分,也用于在除了数据时,具体的指定类型
一个collection形式为:
<collection property="posts"ofType="domain.blog.Post">
<id property="id"column="post_id"/>
<result property="subject"column="post_subject"/>
<result property="body"column="post_body"/>
</collection>
内部依然是使用id和result完成字段和属性的映射
但是collection上使用ofType来指定这个属性的类型,而不是之前的javaType
这也很好理解,对于一对一或者检查的查询,他就是一个对象类型,所以使用JavaType
对于集合的映射,我们很清楚的知道他是一个集合,所以集合类型是他的javaType,比如 javaType="ArrayList",Mybatis 在很多情况下会为你算出来,所以可以省略javaType
但是,什么类型的集合?还需要说明,所以使用ofType进行指定,看起来更加清晰
使用collection的基础形式为:
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<resultMap id="............" type=".................">
<id property="............" column="............"/>
<result property="............" column="............"/> <collection property="............" column="............" ofType="............">
<id property="............" column="............"/>
<result property="............" column="............"/>
</collection> </resultMap>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

集合的嵌套查询

对于collection也可以采用类似association中的select元素进行嵌套查询
原理也是类似,当检索出来结果后,借助于select指定的查询语句,循环查询
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
<resultMap id="blogResult"type="Blog">
<collection property="posts"javaType="ArrayList"column="id"ofType="Post"select="selectPostsForBlog"/>
</resultMap>
<select id="selectBlog"resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
</select> <selectid="selectPostsForBlog"resultType="Post">
SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

ResultMap的嵌套

在前面的叙述中,所有的内部的关联或者集合的属性映射都是直接嵌套在外部ResultMap中的
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
借助于嵌套查询的形式 select属性,可以进行嵌套查询,通过嵌套查询的方式,相当于经过这个select,内部的字段映射部分被路由到另一个ResultMap(ResultType)中了
而不需要在这个ResultMap中逐个重新的进行字段的映射指定
但是select会有1+N的问题,但是使用select时这种使用外部ResultMap(resultType)的形式却是很有实用意义
因为如果可以进行分离,被剥离的那一部分既可以单独使用,又可以嵌套在其他的ResultMap中,组合成更加强大的形式
Mybatis是支持ResultMap嵌套的
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
不仅仅association支持ResultMap的嵌套,collection也是支持的
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
可以看得出来,不管是借助于select的嵌套查询,还是ResultMap的嵌套,都只是在association上或者collection上附加select或者resultMap属性即可
然后就可以省略掉标签内部的字段映射处理了(id和result)
除非开发前对ResultMap的层级结构进行过统一设计布局,否则,内嵌其他人开发的ResultMap,也并不一定总是好事,当内嵌的ResultMap发生变动时,某些情况可能会导致问题
嵌套的ResultMap一定需要是本文件中的吗?当然不是必须的,比如下面示例中借助于:接口的全限定名称进行索引
<association property="courseEntity" column="course_id"
javaType="com.xxx.xxx.domain.CourseEntity" resultMap="com.xxx.xxx.dao.CourseMapper.courseResultMap">
</association>

ResultMap的重用

ResultMap的嵌套也是一种复用,此处说的重用非解耦后的复用
在ResultMap中,我们通过id或者result 将数据库字段和实体类中的属性名进行对应
列名和属性名的对应,以及列名和属性名全部都是固定的了,如下图所示,username就是和author_username对应
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
在之前的例子中,一个blog有一个作者,但是如果一个博客还有一个联合作者怎么办?就像很多书可能不仅仅只有一个作者
在这种场景下:有两个作者,他们的java类型必然都是Author
而且他们的字段也是相同的,但是你不得不将他们进行区分,如下面SQL中所示,关联了两次Author表,通过前缀进行了区分
一种解决方法就是将映射部分也重写两次,就像关联两次那样,仅仅是列名column前缀不同(可以将这两个ResultMap嵌入到blogResult中或者内容移入到外层ResultMap中,总之是写两遍映射)
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
还有一种方法就是借助于columnPrefix,如下图所示,Blog中有两个Author的实例,一个是author另一个是coAuthor,关联关系,使用association
他们都是Author类的实例,所以使用同样的ResultMap,通过columnPrefix对其中一个映射添加列前缀
通过这个列前缀,就相当于有了另外的一个ResultMap,这个ResultMap就是指定的ResultMap中的column中每一个值都加上一个前缀
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

构造方法字段值注入

使用Mybatis的核心就是为了执行SQL以及完成结果映射,结果的映射必然要创建最终需要映射的结果的对象
通过ResultMap中的id和result指定的字段值都是通过setter设置器方法进行值的设置的
既然最终就是要创建一个指定类型并且具有指定属性的对象结果,那么为什么一定非得是通过setter,难道不能在创建对象的时候通过构造方法初始化对象吗?
Mybatis的ResultMap是支持构造方法设置的
对于构造方法的属性值设置,通过constructor进行
将之前的例子稍作修改,增加一个构造方法,复制一个ResultMap,添加constructor,就可以完成映射
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
借助于constructor与使用id和result映射在业务逻辑上没有什么本质的区别,都是将列名与字段进行映射,变的是形式
因为是借助于构造函数,所以constructor中与ResultMap中的其他字段映射是有区别的,不是使用id和result 使用的是 arg 参数
简言之,使用构造方法需要根据方法签名进行匹配,方法签名就是类型和个数的匹配,所以需要javaType
对于有些场景你可能不希望暴露某些属性的共有setter设置器,就可以使用构造方法的形式
上面的示例中没有通过constructor对id进行映射,如果对id进行映射需要使用   <idArg column="id" javaType="int"/>(没写错 就是idArg )
对于使用constructor对值进行解析映射,根本就是匹配正确的构造方法,除了使用javaType还有name,通过name指定构造方法参数的名称
从版本 3.4.3 开始,如果指定了名称name,就不需要严格死板的按照顺序对应了,可以打乱顺序。
没有人会刻意的打乱顺序,但是永远的保证映射的顺序不变动是很难得
Mybatis sql映射文件浅析 Mybatis简介(三) 简介

鉴别器

重新建一个表作为示例,配置信息还是如原来一样,SQL映射文件也是在第一个示例中的XML中编写的
主要的信息如下,表以及数据以及实体类以及映射文件等
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
定义了三个类,一个Person类作为抽象模型(尽管我这个不是抽象类)
一个成人类Adult和一个儿童类Child
Adult增加了company属性,Child增加了school属性
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
每个类都有setter和getter方法,并且还重写了toString方法
映射文件
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
测试类
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
package third;

import first.StudentAnother;
import java.io.InputStream;
import java.util.Collections;
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; public class Test { public static void main(String[] args) throws Exception { /*
* 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的。
* SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。
* 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。
* */
String resource = "config/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"development");
/*
* 从 SqlSessionFactory 中获取 SqlSession
* */
SqlSession session = sqlSessionFactory.openSession();
try {
List<Person> personList = session.selectList("mapper.myMapper.selectPerson");
personList.stream().forEach(i->{
System.out.print(i); System.out.println(i.getClass().getName());
});
} finally {
session.close();
}
} }
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
测试结果
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
Mybatis很神奇的将结果映射为了不同的子类对象
所以说如果一条记录可能会对应多种不同类型的对象,就可以借助于discriminator,通过某个字段的数据鉴别,映射为不同的类
ResultMap中的type对应了父类型,discriminator上的column对应了需要鉴别的列名
每一个case对应着一种类型或者一个ResultMap,通过discriminator就可以根据鉴别的值的不同进行动态的选择
discriminator可以很轻松的处理者中类层次关系中数据的映射
使用discriminator的结果处理步骤
  • MyBatis将会从结果集中取出每条记录,然后比较它的指定鉴别字段的值。
  • 如果匹配任何discriminator中的case,它将使用由case指定的resultMap(resultType)
  • 如果没有匹配到任何case,MyBatis只是简单的使用定义在discriminator块外面的resultMap
如果将映射关系中case后面的值设置为3和4(数据库中只有1和2)
结果如下,仅仅匹配了discriminator外面的部分
Mybatis sql映射文件浅析 Mybatis简介(三) 简介
https://www.cnblogs.com/noteless/p/10340536.html