MyBatis框架之SQL映射和动态SQL
使用MyBatis实现条件查询
1.SQL映射文件:
MyBatis真正的强大之处就在于SQL映射语句,MyBatis专注于SQL,对于开发人员来说也是极大限度的进行SQL调优,以保证性能。下面是SQL映射文件的几个顶级元素的配置:
1.mapper:映射文件的根节点,只有一个属性namespace(命名空间),作用如下:
(1)用于区分不同的mapper,全局唯一。
(2)绑定DAO接口,即面向接口编程,当绑定一个接口,就不用写此接口的实现类,会通过接口的完全限定名找到对应的mapper配置来执行SQL语句,所以,namespace的命名必须要写接口的完全限定名。
2.cache:配置给定命名空间的缓存。
3.cache-ref:从其他命名空间引用缓存配置。
4.resultMap:用来描述数据库结果集和对象的对应关系。
5.sql:可以重用的SQL块,也可以被其他语句引用。
6.insert:映射插入语句。
7.update:更新映射语句。
8.delete:删除映射语句。
9.select:映射查询语句。
2.使用select完成单条件查询
<select id = "GetUserByName" resultType = "User" parameterType = "string">
select * from user where name like concat('%',#{name},'%') //按照姓名模糊查询。
</select>
这是一个id为GetUserByName的映射语句,参数类型为string,返回类型为User。
#{参数名}:告诉MyBatis生成的PreparedStatement参数,相对于JDBC,改参数被标识为‘?’。
id:命名空间的唯一标识符,可以被用来引用这条语句。
parameterType:表示查询语句传入参数的类型和完全限定名或别名。支持基础数据类型和复杂数据类型。上述实例中传入的参数是一个别名,代表String。
别名与Java类型映射
别名 | 映射的类型 | 别名 | 映射的类型 |
string | String | double | Double |
byte | Byte | float | Float |
long | Long | boolean | Boolean |
short | Short | date | Date |
int | Integer | map | Map |
integer | Integer | hashmap | HashMap |
arraylist | ArrayList | list | List |
resultType:查询语句返回结果类型的完全限定名或别名。别名使用方式和parameterType是一样的。
2.使用select完成多条件查询
使用复杂数据类型,把条件参数封装为对象、Map进行入参。
不管什么类型的参数,或者多少个参数,都可以封装为一个Map进行入参,通过Map的key进行获取传入的值。
<select id="GetUserByNameAndRoleId" resultType="User"
parameterType="map">
select * from smbms_user where userName like
CONCAT('%',#{userName},'%')
and userRole = #{userRole}
</select>
3.使用resultMap完成查询结果的展现
resultMap:做自定义映射,实体类属性名和数据库列名不一致的情况下,并且可以指定要显示的列,使用灵活 应用广泛。
<resultMap type="User" id="userMap">
<id column="id" property="id"/>
<result column="userName" property="Name"/> //字段名和属性名不一致的情况下。
</resultMap>
属性和子节点:
id:唯一标识,此id值用于select元素resultMap属性的引用。
type:标识该resultMap的映射结果类型。
result子节点:标识一些简单属性,其中column属性代表数据库的字段名,property代表查询出来的字段名映射到pojo类的某个属性。
id子节点:与result子节点作用一样,一般表示数据库的主键列。
-------------------------------------------------------------------------------------------------------
resultType和resultMap的对比如下 :
1.resultType:直接表示返回类型, 包括基本数据类型和复杂数据类型。
2.resultMap:外部resultMap定义的引用,通过对应的外部resultMap的id,表示结果映射到哪个resultMap上,一般用于字段名和属性名不一致的情况,或者需要做复杂的联合查询以便自由控制映射结果。
3.两者的关联
当进行查询时,查询出来的每个字段都会放在一个Map里,当查询元素返回属性是resultType的时候,会将键值对取出赋所指定的属性。其实MyBatis的每个查询映射的返回类型都是resultMap,只是当我们使用resultType的时候,会自动把对应的值赋给所指定的对象属性,当使用resultMap时候,因为map不是很好的表示领域,我们就进一步的转化为对应的实体对象。resultMap主要作用于复杂的联合查询上。
注意:resultType和resultMap本质是一样的,都是Map数据结构,但是二者不能同时存在。
4.resultMap的自动映射级别:默认级别为PARTIAL,也可以在settings更改值。
1 <settings>
<!-- 设置resultMap的自动映射级别为NONE(禁止自动匹配) -->
<setting name = "autoMappingBehavior" value = "NONE">
</settings>
4.使用MyBatis实现增删改操作
1.使用insert完成增加操作
<insert id="add" parameterType="User">
INSERT INTO user(userName,userCode) VALUES(#{userName},#{userCode})
</insert>
2.使用update完成修改操作
<update id="update" parameterType="User">
UPDATE user SET userName= #{userName},userCode= #{userCode} WHERE id = #{id}
</update>
3.使用delete完成删除操作
<delete id="User" parameterType="integer">
delete from user
where id = #{id}
</delete>
元素中的属性:
id:与select元素id一样,命名空间的唯一标识符。
parameterType:传入参数的类型的完全限定名或者别名。
对于增删改操作的注意事项:
(1)该类型的操作本身默认返回执行SQL影响的行数,所以DAO层的接口方法返回值一般为int类型,最好不要boolean类型。
(2)insert、update、delete元素中均没有resultType属性,只有查询操作需要对返回结果类型(resultType/resultMap)进行相应的指定。
5.使用@param注解实现多参数入参
使用注解用来传入多个参数,相当于给该参数重命名,在SQL映射文件中需要使用#{注解名称}来传入参数。
public user GetUserByIdAndName(@Param("id") Integer id,@Param("Name") String Name);
当参数为基础类型时,无论是多参数还是单参数,都使用@param注解进行参数的传递为好!
使用resultMap实现高级结果映射
1.association:
映射到JavaBean的某个复杂的”数据类型”属性,仅处理一对一的关联关系。
<resultMap type="SMS_USER" id="userMap">
<id column="id" property="id" />
<result column="userName" property="userName" />
<result column="phone" property="phone" />
<association property="role" javaType="SMS_Role">
<id column="id" property="id" />
<result column="roleName" property="roleName" />
</association>
</resultMap>
association的属性节点:
property:映射数据库列的实体对象属性名。
javaType:完整的java类名和限定名。propert所映射的属性的类型。
子元素:id:一般为映射主键,可以提高性能。
result:
column:映射的数据库的字段名。
property:映射的数据列对应的实体对象属性。
2.collection:
映射到JavaBean的某个复杂的”数据类型”属性,这个属性是一个集合列表,处理一对多的关联关系。
<resultMap type="SMS_USER" id="userMapAddress">
<id column="id" property="id"/>
<result column="userName" property="userName"/>
<collection property="lists" ofType="SMS_Address">
<id column = "id" property = "id">
<result column="addressDesc" property="addressDesc"/>
</collection>
</resultMap>
ofType:完整的java类名和限定名。propert所映射的属性的类型。
其余和association基本一致。
MyBatis缓存
1.一级缓存:基于PerpetualCache(MyBatis自带)的HashMap本地缓存。作用域在Session域内,当session flush或者close之后,该缓存被清空。
2.二级缓存:global Cache,超出session范围之外,可以被所有SqlSession共享。开启它只需在MyBatis的核心配置文件 settings 设置即可。
补充:一级缓存缓存的是SQL语句,二级缓存缓存的是结果对象。
3.二级缓存配置:
(1)开启二级缓存;
<settings>
<setting name="cacheEnabled" value = "true"/>
<settings>
(2)mapper文件中设置缓存,默认是没有开启缓存的。作用域是针对namespace而言的,只在namespace内的查询才能共享这个cache。
(3)对个别查询进行缓存,单独设置cache:
<select id = "getUser" resultType = "User" useCache = "true">
...........
</select>
补充:对MyBatis的缓存了解就可以了,对结果集做缓存并不是MyBatis所擅长的,而且性能也不是很好,它专心做的应该是SQL映射。
------------------------------------------------------------------------------------------------------------------------------------
动态SQL
一、使用动态SQL完成多条件查询。
动态SQL基于OGNL的表达式,我们可以方便的在SQL语句中实现某些逻辑,用于实现动态SQL元素如下:
if:利用if实现简单的条件选择。
choose(when,otherwise):相当于java中的switch语句,通常与when和otherwise搭配。
set:解决动态更新语句。
trim:灵活的去除多余的关键字。
foreach:迭代一个集合,通常用于in条件。
二、if+where实现多条件查询
<select id="ShowUser" parameterType="Map" resultType="SMS_USER">
select * from smbms_user
<where>
<if test="userRole != null and userRole != 0">
userRole = #{userRole}
</if>
<if test="userName != null and userName != ''">
and userName like CONCAT('%',#{userName},'%')
</if>
</where>
</select>
where元素可以智能的处理and 和 or 的多余问题, 不需担心多余关键字导致语法错误。
if元素的test用于判断表达式是否符合,符合则继续拼接SQL语句。
三、if+trim+foreach实现多条件查询
1 <select id="listsByInAndGender" resultType="SMS_USER">
select * from smbms_user
<trim prefix="where" prefixOverrides="and | or">
<if test="userIds!=null">
id in
<foreach collection="userIds" item="ids" open="(" close=")" separator=",">
#{ids}
</foreach>
</if>
<if test="gender != null and gender != 0">
and gender = #{gender}
</if>
</trim>
14 </select>
(1)trim的属性:
prefix:前缀: 作用是通过自动识别是否有返回值后,在trim包含的内容上加上前缀,如上述示例的where。
suffix:后缀: 作用是在trim包含的内容上加上后缀。
prefixOverrides: 对于trim包含内容的首部进行指定内容,(如上述示例的 and | or) 的忽略(去余);
suffixOverrides: 对于trim包含内容的首位部进行指定内容的忽略。
(2)foreach的属性:
item:表示集合中每一个元素进行迭代时的别名。
index: 指定一个名称,表示在迭代的过程中,每次迭代到的位置。
open:表示该语句以什么开始(既然是in条件语句,必然是 ' ( ' 开始)
separator: 表示每次进行迭代的时候以什么符号作为分隔符(既然是in条件语句,必然是 ' , ' 分隔)
close: 表示该语句以什么结束(既然是in条件语句,必然是 ' ) ' 结束)
collection:最关键,并且最容易出错的属性。需注意,该属性必须指定,不同情况下,该属性值是不同的,主要有三种情况:
若传入的参数是单参数且类型为一个List的时候,属性值为list;
若传入的参数是单参数且类型为一个数组的时候,属性值为array;
若传入的参数为多参数时,就需要封装为一个map集合进行处理。属性值为Map的key;
使用set更新操作,类似于上述示例使用方法:
<update id="UpdateUser" parameterType="SMS_USER">
update smbms_user
<trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
<if test="userName != null and userName != ''">
userName = #{userName},
</if>
<if test="gender != null and gender != 0">
gender = #{gender},
</if>
<if test="address != null and address != ''">
address = #{address},
</if>
</trim>
</update>
三、choose(when、otherwise)
<select id="QueryAllByChoose" resultType="SMS_provider">
select * from smbms_provider where 1 = 1
<choose>
<when test="proCode != null and proCode != ''">
and proCode like CONCAT('%',#{proCode},'%')
</when>
<when test="proName != null and proName != ''">
and proName like CONCAT('%',#{proName},'%')
</when>
<when test="proContact != null and proContact != ''">
and proContact like CONCAT('%',#{proContact},'%')
</when>
<otherwise>
and YEAR(creationDate) = 2016
</otherwise>
</choose>
</select>
when元素:当test属性中的条件满足时,就会输出when元素中的内容,并且当when中一旦有条件满足时,就会跳出choose,所以只有一个条件会被输出。
otherwise元素:当when中的所有条件都不满足时,则会输出此元素的内容。
四、MyBatis实现分页功能
1.使用聚合函数获得总记录数-
2.实现分页通过limit(起始位置,页面显示量)
补充:起始位置的下标 = (当前页码 - 1 ) * 页面显示量
<!-- 多条件筛选分页 -->
<select id="UserPage" parameterType="map" resultType="SMS_USER">
select * from smbms_user
<trim prefix="where" prefixOverrides="and | or">
<if test="userName != null and userName != ''">
userName like concat('%',#{userName},'%')
</if>
<if test="userRole != null and userRole != 0">
and userRole = #{userRole}
</if>
</trim>
limit #{startRow},#{pageSize}
</select>
MyBatis框架之SQL映射和动态SQL的更多相关文章
- 小峰mybatis(5)mybatis使用注解配置sql映射器--动态sql
一.使用注解配置映射器 动态sql: 用的并不是很多,了解下: Student.java 实体bean: package com.cy.model; public class Student{ pri ...
- MyBatis基础入门《十七》动态SQL
MyBatis基础入门<十七>动态SQL 描述: >> 完成多条件查询等逻辑实现 >> 用于实现动态SQL的元素主要有: > if > trim > ...
- .Net程序员学用Oracle系列(28):PLSQL 之SQL分类和动态SQL
1.SQL 语句分类 1.1.分类方法及类型 1.2.数据定义语言 1.3.数据操纵语言 1.4.其它语句 2.动态 SQL 理论 2.1.动态 SQL 的用途 2.2.动态 SQL 的语法 2.3. ...
- PL/SQL开发中动态SQL的使用方法
一般的PL/SQL程序设计中,在DML和事务控制的语句中可以直接使用SQL,但是DDL语句及系统控制语句却不能在PL/SQL中直接使用,要想实现在PL/SQL中使用DDL语句及系统控制语句,可以通过使 ...
- 数据库系统学习(十)-嵌入式SQL语言之动态SQL
第十讲 嵌入式SQL语言之动态SQL 静态SQL 区别变量和属性:高级语言向嵌入式SQL传递变量的方法 动态SQL 动态构造SQL语句是应用程序员必须掌握的重要手段 SQL语句的动态构造示例 根据界面 ...
- (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql
http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...
- Java数据持久层框架 MyBatis之API学习七(动态 SQL详解)
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
- (转)Mybatis高级映射、动态SQL及获得自增主键
原文:http://www.cnblogs.com/edwinchen/p/4105278.html?utm_source=tuicool&utm_medium=referral 一.动态SQ ...
- Mybatis高级映射、动态SQL及获得自增主键
一.动态SQL 相信大家在用mybatis操作数据库时时都会碰到一个问题,假如现在我们有一个关于作者的list authorList,需要根据authorList里已有的作者信息在数据库中查询相应作者 ...
随机推荐
- Windows RabbitMQ 安装
操作系统 Win10 企业版 目标: 在win10上安装RabbitMQ 安装步骤 1.安装RabbitMQ需要先安装Erlang语言开发包,下载地址:http://www.erlang.org/d ...
- 瑞芯微RK3399宣布系统开源,进入百余种行业市场!
集微网消息,2月24日瑞芯微官方突然宣布, Rockchip RK3399Linux系统开源!作为Rockchip旗舰级芯片,RK3399具有高性能.高扩展.全能型应用特性. 这一重磅消息立马刷爆朋友 ...
- KmdKit4D 0.01正式版发布了(0.02版已放出)(Delphi做驱动)
此版本较0.01预览版已经有了脱胎换骨的变化,主要表现在以下几个方面: 1.对程序的结构进行了调整,将原来的ntutils.dcu分成fcall.dcu.halfcall.dcu和macros. ...
- Memory Ordering (注意Cache带来的副作用,每个CPU都有自己的Cache,内存读写不再一定需要真的作内存访问)
Memory Ordering Background 很久很久很久以前,CPU忠厚老实,一条一条指令的执行我们给它的程序,规规矩矩的进行计算和内存的存取. 很久很久以前, CPU学会了Out-Of ...
- 预编译加速编译(precompiled_header),指定临时文件生成目录,使项目文件夹更干净(MOC_DIR,RCC_DIR, UI_DIR, OBJECTS_DIR),#pragma execution_character_set("UTF-8")"这个命令是在编译时产生作用的,而不是运行时
预编译加速编译 QT也可以像VS那样使用预编译头文件来加速编译器的编译速度.首先在.pro文件中加入: CONFIG += precompiled_header 然后定义需要预编译的头文件: PREC ...
- Webapi实现websocket实时通讯
应用场景:前端页面发起一个websocket请求与后端进行实时通讯.后端监听某端口获取数据,将监听到的数据加工处理,通过websocket发送到前端. 这里只提供后台的处理方案仅供参考. 1.后端监听 ...
- Hexo+NexT(一):在Windows下安装Hexo+NexT及搭建博客
阅读本篇之前,假定读者已经有了Node.js的基础,如需要补充Node.js知识的,请自行百度. Hexo是在Node.js框架下的一个项目,利用Node.js提供的强大功能,完成从Markdown到 ...
- 解决安装Oracle本地可以访问客户端不能访问
现象:本地需要修改监听为localhost -->win+r--> sqlplus system/123@xxdb 可以登陆,远程客户端不能登陆:需要将监听修改为IP地址,重启监听:远程可 ...
- Django之forms组件进阶
Django Form表单组件 Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要 ...
- 支持向量机 (二): 软间隔 svm 与 核函数
软间隔最大化(线性不可分类svm) 上一篇求解出来的间隔被称为 "硬间隔(hard margin)",其可以将所有样本点划分正确且都在间隔边界之外,即所有样本点都满足 \(y_{i ...