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

 
简介
除了配置相关之外,另一个核心就是SQL映射,MyBatis 的真正强大也在于它的映射语句。
Mybatis创建了一套规则以XML为载体映射SQL
之前提到过,各项配置信息将Mybatis应用的整体框架搭建起来,而映射部分则是准备了一次SQL操作所需的信息
一次SQL执行的主要事件是什么?
输入参数解析,绝大多数SQL都是需要参数的
SQL,通过SQL与数据库交互,所以最根本的是SQL,如果连SQL都没有,还扯个蛋蛋?
结果映射,Mybatis可以帮我们完成字段与Java类型的映射
所以说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 映射文件的核心内容
如下图所示:
而对于数据库的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 
每种类型又都有各自的属性设置,有一些是共同的,有一些是特有的
下图如果不清楚,请到评论区中,右键,新标签查看图片,可以查看到大图

属性角度解析

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

额外的馈赠-语法糖

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

........

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

深入映射

参数(Parameters)细节配置

<selectid="selectPerson"parameterType="int"resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
示例中入参类型通过parameterType指定为int,参数占位符为#{id},这是最简单的一种形式了,入参只是一个Java基本类型(非自定义的对象类型)
对于对象类型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>
不仅仅支持对象,而且还支持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}的形式进行读取
<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很多时候都可以自动处理,但是你可以对他进行显式的明确指明,比如
 
#{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可以完成一些基本的诉求,比如从单表到对应实体类对象的映射,能够自动的根据字段名称和属性名称进行匹配
 
但是如果名称不对应又该怎么办?
如果你的实体中的属性名称为userName,数据库字段名为name,Mybatis真的敢擅自的将这两者对应起来么?
如下图所示,将之前的第一个示例稍作修改,增加一个StudentAnother,name更改为了userName,并将测试代码稍作修改
从结果可以看得到,实体中的userName是null ,Mybatis肯定不敢擅自映射
一种可行的方式是使用别名,通过数据库字段AS设置别名,就可以成功的完成映射
通过别名,将数据库列名通过别名与属性字段建立映射关系,然后Mybatis就可以进行自动匹配了
但是这种形式如果有多条SQL,每个SQL中都需要有别名,而且,如果后续有原因修改对象的字段名字,怎么办?
 
另外的方式就是使用ResultMap,ResultMap的基础用法就是相当于设置别名
但是借助于ResultMap,将别名的映射关系,维护在ResultMap中,所有使用到此映射类型的SQL都只需要关联这个ResultMap即可,如果有变更,仅仅需要变更ResultMap中的属性字段对应关系
所有的SQL中的内容并不需要变动
 
如下图所示,SQL中字段与实体类中不匹配,查询的结果为null
右侧通过ResultMap将userName与列名name进行了映射,就可以成功读取数据
 
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用于更加细致的解析映射
所以说基本元素为:

ResultMap-高级映射

ResultMap当然不仅仅是像上面那样只是别名的转换,还可以进行更加复杂的映射
 
对于结果集返回有哪些场景?
“将一行记录映射为一个对象”与“将多行记录映射为对象列表”这两者本质是一样的,因为所需要做的映射是一样的
比如上面数据库列名name到字段userName 的映射,不管是一行记录还是多行记录,他们都是一样的
所以下面就以一个对象为例
 
单纯的映射
比如上面的例子,数据库列名与实体类中的字段一一对应(尽管名称不完全匹配,但是仍旧是一一对应的)
组合的映射
对于关系型数据库存在着关联关系的说法,一对一,一对多等
这些关联关系最终也是要映射到对象中的, 所以对象中经常也会存在多种对应关系
比如下面官方文档中的示例----查询博客详情 
一个博客Blog 对应着一个作者Author ,一个作者可能有多个博文Post,每篇博文有零或多条的评论Post_Tag 和标签Tag
<!-- 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>
对于实体类,一种可能的形式如下
Blog中有一个Author,有一个List<Post> ,每一个Post中又有List<Comment> 和  List<Tag>
 
可以看得出来对于组合映射又有一对一以及一对多两种形式
(尽管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?他的直接外层是谁就是谁!
<association property="author"column="blog_author_id"javaType="Author">
<id property="id"column="author_id"/>
<result property="username"column="author_username"/> </association>
对于association的基本格式如下,相当于在基础的ResultMap中插入了一个“一对一”的对应
<resultMap id="............" type=".................">
<id property="............" column="............"/>
<result property="............" column="............"/>
<association property="............" column="............" javaType="............">
<id property="............" column="............"/>
<result property="............" column="............"/> </association> </resultMap>
association中对于字段和属性的映射也是使用id和result,对于唯一标志使用id来表示

关联的嵌套查询

对于一个association还可以对他进行嵌套查询,也就是在查询中进行查询
比如官方示例中
<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>
当执行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} ”的形式
比如:
 
上面就是通过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的基础形式为:
<resultMap id="............" type=".................">
<id property="............" column="............"/>
<result property="............" column="............"/> <collection property="............" column="............" ofType="............">
<id property="............" column="............"/>
<result property="............" column="............"/>
</collection> </resultMap>

集合的嵌套查询

对于collection也可以采用类似association中的select元素进行嵌套查询
原理也是类似,当检索出来结果后,借助于select指定的查询语句,循环查询
<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>

ResultMap的嵌套

在前面的叙述中,所有的内部的关联或者集合的属性映射都是直接嵌套在外部ResultMap中的
 
借助于嵌套查询的形式 select属性,可以进行嵌套查询,通过嵌套查询的方式,相当于经过这个select,内部的字段映射部分被路由到另一个ResultMap(ResultType)中了
而不需要在这个ResultMap中逐个重新的进行字段的映射指定
但是select会有1+N的问题,但是使用select时这种使用外部ResultMap(resultType)的形式却是很有实用意义
因为如果可以进行分离,被剥离的那一部分既可以单独使用,又可以嵌套在其他的ResultMap中,组合成更加强大的形式
Mybatis是支持ResultMap嵌套的
不仅仅association支持ResultMap的嵌套,collection也是支持的
 
可以看得出来,不管是借助于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对应
 
在之前的例子中,一个blog有一个作者,但是如果一个博客还有一个联合作者怎么办?就像很多书可能不仅仅只有一个作者
在这种场景下:有两个作者,他们的java类型必然都是Author
而且他们的字段也是相同的,但是你不得不将他们进行区分,如下面SQL中所示,关联了两次Author表,通过前缀进行了区分
一种解决方法就是将映射部分也重写两次,就像关联两次那样,仅仅是列名column前缀不同(可以将这两个ResultMap嵌入到blogResult中或者内容移入到外层ResultMap中,总之是写两遍映射)
 
还有一种方法就是借助于columnPrefix,如下图所示,Blog中有两个Author的实例,一个是author另一个是coAuthor,关联关系,使用association
他们都是Author类的实例,所以使用同样的ResultMap,通过columnPrefix对其中一个映射添加列前缀
通过这个列前缀,就相当于有了另外的一个ResultMap,这个ResultMap就是指定的ResultMap中的column中每一个值都加上一个前缀

构造方法字段值注入

使用Mybatis的核心就是为了执行SQL以及完成结果映射,结果的映射必然要创建最终需要映射的结果的对象
通过ResultMap中的id和result指定的字段值都是通过setter设置器方法进行值的设置的
既然最终就是要创建一个指定类型并且具有指定属性的对象结果,那么为什么一定非得是通过setter,难道不能在创建对象的时候通过构造方法初始化对象吗?
Mybatis的ResultMap是支持构造方法设置的
对于构造方法的属性值设置,通过constructor进行
将之前的例子稍作修改,增加一个构造方法,复制一个ResultMap,添加constructor,就可以完成映射
 
借助于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,就不需要严格死板的按照顺序对应了,可以打乱顺序。
没有人会刻意的打乱顺序,但是永远的保证映射的顺序不变动是很难得

鉴别器

重新建一个表作为示例,配置信息还是如原来一样,SQL映射文件也是在第一个示例中的XML中编写的
主要的信息如下,表以及数据以及实体类以及映射文件等
 
定义了三个类,一个Person类作为抽象模型(尽管我这个不是抽象类)
一个成人类Adult和一个儿童类Child
Adult增加了company属性,Child增加了school属性
每个类都有setter和getter方法,并且还重写了toString方法
 
映射文件
 
测试类
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很神奇的将结果映射为了不同的子类对象
 
所以说如果一条记录可能会对应多种不同类型的对象,就可以借助于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外面的部分
 
https://www.cnblogs.com/noteless/p/10340536.html

Mybatis sql映射文件浅析 Mybatis简介(三) 简介的更多相关文章

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

    简介 除了配置相关之外,另一个核心就是SQL映射,MyBatis 的真正强大也在于它的映射语句. Mybatis创建了一套规则以XML为载体映射SQL 之前提到过,各项配置信息将Mybatis应用的整 ...

  2. Mybatis SQL映射文件详解

    Mybatis SQL映射文件详解 mybatis除了有全局配置文件,还有映射文件,在映射文件中可以编写以下的顶级元素标签: cache – 该命名空间的缓存配置. cache-ref – 引用其它命 ...

  3. MyBatis -- sql映射文件具体解释

    MyBatis 真正的力量是在映射语句中. 和对等功能的jdbc来比价,映射文件节省非常多的代码量. MyBatis的构建就是聚焦于sql的. sql映射文件有例如以下几个顶级元素:(按顺序) cac ...

  4. SSM - Mybatis SQL映射文件

    MyBatis 真正的力量是在映射语句中.和对等功能的jdbc来比价,映射文件节省很多的代码量.MyBatis的构建就是聚焦于sql的. sql映射文件有如下几个顶级元素:(按顺序) cache配置给 ...

  5. 初始MyBatis、SQL映射文件

    MyBatis入门 1.MyBatis前身是iBatis,是Apache的一个开源项目,2010年这个项目迁移到了Google Code,改名为MyBatis,2013年迁移到GitHub.是一个基于 ...

  6. MyBatis 创建核心配置文件和 SQL 映射文件

    Mybatis 的两个配置文件(mybatis-config.xml  和 xxxMapper.xml)都为 xml 类型,因此在 eclipse 中创建 xml 文件命名为相应的 mybatis-c ...

  7. MyBatis 的基本要素—SQL 映射文件

    MyBatis 真正的强大在于映射语句,相对于它强大的功能,SQL 映射文件的配置却是相当简单.对比 SQL 映射配置和 JDBC 代码,发现使用 SQL 映射文件配置可减少 50% 以上的代码,并且 ...

  8. Mybatis(二) SQL映射文件

    SQL映射文件 单条件查询 1. 在UserMapper接口添加抽象方法 //根据用户名模糊查询 List<User> getUserListByName(); 2. 在UserMappe ...

  9. MyBatis学习-映射文件标签篇(select、resultMap)

    MyBatis 真正的核心在映射文件中.比直接使用 JDBC 节省95%的代码.而且将 SQL 语句独立在 Java 代码之外,可以进行更为细致的 SQL 优化. 一. 映射文件的顶级元素 selec ...

随机推荐

  1. mysql:Cannot proceed because system tables used by Event Scheduler were found damaged at server start

    mysql 5.7.18 sqlyog访问数据库,查看表数据时,出现 Cannot proceed because system tables used by Event Scheduler were ...

  2. PHP07

    PHP07 1.cookie 2.使用php操作cookie 设置响应头(header)中的Set-Cookie可以下发小票 检查-network-响应头处可查看所设置cookie 检查-applic ...

  3. pygame-KidsCanCode系列jumpy-part4-弹跳

    终于要到弹跳环节了,向上弹跳其实很简单,按下空格触发时,只要把y轴速度给一个向上的速度即可. Player类,新加一个jump()方法: def jump(self): self.vel.y = -2 ...

  4. 前端工程化系列[03]-Grunt构建工具的运转机制

    在前端工程化系列[02]-Grunt构建工具的基本使用这篇文章中,已经对Grunt做了简单的介绍,此外,我们还知道了该如何来安装Grunt环境,以及使用一些常见的插件了,这篇文章主要介绍Grunt的核 ...

  5. MySQL监控全部执行过的sql语句

    MySQL监控全部执行过的sql语句 查看是否开启日志记录show variables like “general_log%” ; +——————+———-+|Variable_name|Value| ...

  6. CVPR论文《100+ Times Faster Weighted Median Filter (WMF)》的实现和解析(附源代码)。

    四年前第一次看到<100+ Times FasterWeighted Median Filter (WMF)>一文时,因为他附带了源代码,而且还是CVPR论文,因此,当时也对代码进行了一定 ...

  7. 大疆无人机M100相关问题解决过程

    1.遥控器升级问题 iOS端使用app升级,重复尝试了5次+,还是无法升级.卸载app重新安装,依旧是无法升级.使用Android app升级,一次搞定. 2.飞行器固件升级(云台别选错了) http ...

  8. REST API 调用 方法

    METHOD      DESCRIPTION GET         Retrieves the specified resource POST        Creates a resource ...

  9. 同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  10. weak_ptr<T>智能指针

    weak_ptr是为配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手,而不是智能指针,因为它不具有普通指针的行为,没有重载operator*和operator-&g ...