Mybatis(二):Mybatis的映射文件sqlmapper详解
MyBatis 真正的力量是在映射语句中。这里是奇迹发生的地方。对于所有的力量,SQL 映射的 XML 文件是相当的简单。当然如果你将它们和对等功能的 JDBC 代码来比较,你会发现映射文件节省了大约 95%的代码量。MyBatis 的构建就是聚焦于 SQL 的,使其远离于普通的方式。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
- cache – 配置给定命名空间的缓存。
- cache-ref – 从其他命名空间引用缓存配置。
- resultMap – 最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加载你的对象。
- parameterMap – 已经被废弃了!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除。这里不会记录。
- sql – 可以重用的 SQL 块,也可以被其他语句引用。
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射查询语句
1)cache
参阅这篇文章里的二级缓存段落 MyBatis缓存详解
2)sql
用来定义可重用的sql语句块。
<sql id="column">
name,species,sex
</sql>
然后在sql映射中用<include/>标签引入:
<select id="selectPetByName" parameterType="string" resultType="hashmap">
select
<include refid="column"/>
from pet
where name = #{name}
</select>
这样就可以减少大量重复的sql书写工作。
3)resultMap
resultMap是mybatis中最强大最有用的配置,它可以帮助我们告别繁琐的while + resultSet.get(..) 而实现自动封装。
对于简单的sql查询,不需要配置resultMap,用hashmap来封装结果集会更好,这样会以字段名称为key,字段值为value来封装结果集:
<select id="selectAllColumn" parameterType="string" resultType="hashmap">
select <include refid="column"/> from pet where name = #{name}
</select>
但有时我们需要得到一个JavaBean对象,有两种方式可以实现,一种用reusltType来制定结果类型,另一种用resultMap来映射结果集和JavaBean对象:
第一种方式:
<select id="selectOneByName" parameterType="string" resultType="com.mybatis.test.entity.Pet">
select <include refid="column"/>
from pet where name = #{name}
</select>
这样mybatis就会把查询出的结果封装到Pet对象中。
第二种方式:
配置resultMap
<resultMap type="com.mybatis.test.entity.Pet" id="petMap">
<result column="name" property="name" javaType="string" jdbcType="VARCHAR"/>
<result column="species" property="species" javaType="string" jdbcType="VARCHAR" typeHandler="com.mybatis.test.handler.MyStringTypeHandler"/>
<result column="sex" property="sex" typeHandler="com.mybatis.test.handler.MyStringTypeHandler"/>
</resultMap>
在sql映射中配置resultMap:
<select id="cthSelect" resultMap="petMap">
select <include refid="column"/>
from pet
</select>
实际上应用第一种配置方式时,mybatis会在幕后根据字段名称自动创建一个resultMap。若表字段名称与JavaBean中的字段名称不匹配,还可以利用sql语句的as来修改sql结果集的字段名,使之与JavaBean中的字段名相匹配:
<select id="selectOneByName" parameterType="string" resultType="com.mybatis.test.entity.Pet">
select
name as name,
species as species,
sex as sex
from pet where name = #{name}
</select>
但有的时候事情并没有这么简单,我们在很多情况下需要做一对多或多对一的联合查询,但把这些重组的字段再组合到一个新的bean对象中是不现实的,这样就需要对多个表和bean利用resultMap做联合配置,以满足实际的需求。
下面以经典的“部门”对“员工”为例,做一对多和多对一的映射配置:
Employee Bean:
private Integer id;
private String employeeName;
private Integer age;
private Department department = new Department();
Department Bean:
private Integer id;
private String departmentName;
private List<Employee> employees;
一个部门对应多个员工,而一个员工属于一个部门,我们分别从部门和员工的角度出发,来做一对多和多对一的映射。
员工-部门的多对一映射:
<resultMap type="com.mybatis.test.entity.Employee" id="employeeMap">
<!--
id : 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能.
result : 注入到字段或 JavaBean 属性的普通结果
association : 一个复杂的类型关联;许多结果将包成这种类型.
collection : 复杂类型的集 -->
<id property="id" column="id"/>
<result property="employeeName" column="name"/>
<result property="age" column="age"/>
<association property="department" javaType="Department">
<id property="id" column="id"/>
<result property="departmentName" column="department_name"/>
</association>
</resultMap>
用<association/>来指定每一个员工多对应的部门。
部门-员工的一对多映射:
<resultMap type="Department" id="departmentMap">
<id property="id" column="id"/>
<result property="departmentName" column="department_name"/>
<collection property="employees" ofType="Employee" column="dept_id">
<id property="id" column="id"/>
<result property="employeeName" column="name"/>
<result property="age" column="age"/>
</collection>
</resultMap>
利用<collection/>来制定多是一方。在配置多对一关系时,需要在<collection/>中制定关联字段,column="dept_id",这样mybatis就会根据这个字段来找出所有属于该部门的员工,并将其封装到集合中。
在定义resultMap时,还可以利用javaType、jdbcType和typeHandler来实现java数据类型和数据库字段类型的对应关系及其特定的操作动作,eg:
在mybatis核心配置文件中生命自定义类型处理器:
<typeHandlers>
<typeHandler javaType="string" jdbcType="VARCHAR" handler="com.mybatis.test.handler.MyStringTypeHandler"/>
</typeHandlers>
自定义类型处理器:
package com.mybatis.test.handler; import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler; public class MyStringTypeHandler implements TypeHandler<String>{ @Override
public void setParameter(PreparedStatement ps, int i, String parameter,
JdbcType jdbcType) throws SQLException {
if("".equals(parameter) || "null".equals(parameter)
|| parameter == null || "NULL".equals(parameter)){
parameter = "blank";
}
ps.setString(i, parameter);
} @Override
public String getResult(ResultSet rs, String columnName)
throws SQLException {
String result = rs.getString(columnName);
if("null".equals(result) || "".equals(result)
|| result == null || "NULL".equals(result)){ result = "blank";
}
return result;
} @Override
public String getResult(ResultSet rs, int columnIndex) throws SQLException {
String result = rs.getString(columnIndex);
if("null".equals(result) || "".equals(result)
|| result == null || "NULL".equals(result)){
result = "blank";
}
return result;
} @Override
public String getResult(CallableStatement cs, int columnIndex)
throws SQLException {
String result = cs.getString(columnIndex);
if("null".equals(result) || "".equals(result)
|| result == null || "NULL".equals(result)){
result = "blank";
}
return null;
} }
该类型处理器既可以用于设置参数时、也可以用于获取结果时对空值的处理。
在resultMap中进行配置:
<resultMap type="com.mybatis.test.entity.Pet" id="petMap">
<result column="name" property="name" javaType="string" jdbcType="VARCHAR"/>
<result column="species" property="species" javaType="string" jdbcType="VARCHAR" typeHandler="com.mybatis.test.handler.MyStringTypeHandler"/>
<result column="sex" property="sex" typeHandler="com.mybatis.test.handler.MyStringTypeHandler"/>
</resultMap>
这样,如果从数据库表中查询出的结果为null时,就会用自定义类型处理器中的方式进行处理。
在设置参数的时候可以像下面这样应用自定义类型处理器对参数进行处理:
<insert id="insertNullByMyTypeHandler" parameterType="Pet">
insert into pet
(<include refid="column"/>)
values
(
#{name,jdbcType=UNDEFINED,javaType=string,handler=com.mybatis.test.handler.MyTypeHandler},
#{species},
#{sex}
)
</insert>
3)insert、update、delete
这三个标签分别配置对应的sql语句,由于这三中sql都是DML,所以在用法上基本相同:
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20"> <update
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20"> <delete
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">
id:该sql语句在当前名称空间下的唯一标识符,用户调用该sql语句。
parameterType:sql语句的参数类型,可以是mybatis提供的别名(int、string、hashmap、list等),也可以是自定义类似。需要注意的是,若参数类型为hashmap或自定义bean等,在利用#{fieldName}取得参数的值时用到的名称需要与map中的key或bean中的字段名称保证一致,否则会取不到数据,如果是string或int等,则名称没有现实,只起到标识的作用。
flushCache:刷新缓存,若将该属性设置为true,则调用该sql时,会到时缓存被清空。默认为false。
statementType:设置预编译sql语句的方式,mybatis提供了三种:
STATEMENT,PREPARED,CALLABLE
默认是PREPARED类型。
timeout:设置获取数据库操作结果的最大等事件。默认不对其进行设置,有数据库取得来决定。
4)select
select语句是最常用的数据库操作,相对于DML操作,mybatis对select语句映射的支持明显更强。查询语句的特殊之处在于既有输入也有输出,下面对select语句映射做简要概述。
一个最简单的查询映射:
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
该语句按照id查询一条person记录,其中输入参数是int类型,虽然#{id}中的id与数据表中的id列名保存一致,但前面已经说过,对于基本数据类型的参数,名称没有现实,任何名字mybatis都可以取到参数的值。返回结果是hashmap,也就是Java中对应的HashMap,定义该结果类型后,mybatis会将查询结果封装到一个map对象中,key值为字段名称,value为该字段的值。
Mybatis对select标签提供了丰富的属性,以支持对select语句的更细粒度配置:
<select
id="selectPerson"
parameterType="int"
parameterMap="deprecated"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10000"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">
其中的本分属性前面已经介绍过,这里就不在冗述了。
useCache:配置二级缓存,当mybatis开启二级缓存时,查询有默认是应用二级缓存的,若不想将某一个DQL与二级缓存联系起来,可将该属性设置为false。
fetchSize:设置每次查询的最大返回结果,通常不设置改属性。
Mybatis(二):Mybatis的映射文件sqlmapper详解的更多相关文章
- mybatis映射文件mapper详解
mapper.xml映射文件主要是用来编写sql语句的,以及一些结果集的映射关系的编写,还有就是缓存的一些配置等等. 1.<select>元素 <select>元素就是sql查 ...
- 转载 Spring、Spring MVC、MyBatis整合文件配置详解
Spring.Spring MVC.MyBatis整合文件配置详解 使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. ...
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- Spring MVC、MyBatis整合文件配置详解
Spring:http://spring.io/docs MyBatis:http://mybatis.github.io/mybatis-3/ Building a RESTful Web Serv ...
- 二:SQL映射文件
二:SQL映射文件 1.SQL映射文件: (1)mapper:映射文件的根元素节点,只有一个属性namespace(命名空间) 作用:用于区分不同的mapper全局唯一 绑定dao接口即面向接口编程, ...
- [转]文件IO详解(二)---文件描述符(fd)和inode号的关系
原文:https://www.cnblogs.com/frank-yxs/p/5925563.html 文件IO详解(二)---文件描述符(fd)和inode号的关系 ---------------- ...
- MyBatis 一级缓存、二级缓存全详解(一)
目录 MyBatis 一级缓存.二级缓存全详解(一) 什么是缓存 什么是MyBatis中的缓存 MyBatis 中的一级缓存 初探一级缓存 探究一级缓存是如何失效的 一级缓存原理探究 还有其他要补充的 ...
- 2017.3.31 spring mvc教程(二)核心流程及配置详解
学习的博客:http://elf8848.iteye.com/blog/875830/ 我项目中所用的版本:4.2.0.博客的时间比较早,11年的,学习的是Spring3 MVC.不知道版本上有没有变 ...
- 史上最全的maven pom.xml文件教程详解
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
随机推荐
- 洛谷——P1754 球迷购票问题
题目背景 盛况空前的足球赛即将举行.球赛门票售票处排起了球迷购票长龙. 按售票处规定,每位购票者限购一张门票,且每张票售价为50元.在排成长龙的球迷中有N个人手持面值50元的钱币,另有N个人手持面值1 ...
- 利用 ildasm 修改被编译后DLL文件
在开发中遇到这样一个场景,需要修改一个dll文件(.NET程序集)中某些地方的类型名称,但没有源代码,只能修改IL代码. 操作步骤如下: 1. 运行ildasm ildasm是由微软提供的.NET程序 ...
- [LA 3942] Remember the Word
Link: LA 3942 传送门 Solution: 感觉自己字符串不太行啊,要加练一些蓝书上的水题了…… $Trie$+$dp$ 转移方程:$dp[i]=sum\{ dp[i+len(x)+1]\ ...
- 【bzoj1370】【团伙】原来并查集还能这么用?!
(画师当然是武内崇啦) Description 在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1. 我朋友的朋友是我的朋友: 2. 我敌人的敌人是我的朋友: 所有是朋友的人组成一 ...
- 输入输出流和String的混合使用-替换信息
---恢复内容开始--- package demo; import java.io.BufferedReader; import java.io.BufferedWriter; import java ...
- 输入格式CombineFileInput
此输入格式的作用就是可以将来自多个不同文件的物理块作为一个split,然后由一个map进行处理. http://www.blogjava.net/shenh062326/archive/2012/07 ...
- 动态OSPF配置路由表
动态ospf设置路由表 以Rourer1为例子 (1)首先设置路由器端口ip Router(config)#inter f0/0 Router(config-if)#ip add 192.168.1. ...
- 【转载】Mini2440启动配置文件说明
对于mini2440,虽然root_qtopia这个文件系统的GUI是基于Qtopia的,但其初始化启动过程却是由大部分由busybox完成,Qtopia(qpe)只是在启动的最后阶段被开启. 由于默 ...
- 关于MYsql 多字段排序
SELECT switch_data.* , lan_data.ename FROM switch_data , lan_data WHERE switch_data.address = '佳合丽景' ...
- JS删除数组中某一项或几项的方法汇总
1.JS中的splice方法 splice(index, len, [item]) //注意:该方法会改变原始数组. splice有3个参数,它也可以用来替换/删除/添加数组内某一个或者几个值. ...