1. 准备

请先完成Mybatis实现增删改查(二)Mybatis实现条件查询(三)的基本内容

2. 关于多条件查询的疑问

Mybatis实现条件查询(三)中我们实现了多条件(商品编码、商品名称、商品价格范围)查询商品信息。但是我们现在有了一个新的疑问:在Mybatis实现条件查询(三)中,如果我们只赋值了PartCode查询条件,而没有赋值其他查询条件,那么会发生什么呢?

我们重新修改下main方法(屏蔽了三行代码,如下):

public static void main(String[] args) {
QryPartParam qryPartParam = new QryPartParam();
qryPartParam.setPartCode("001-0001");
//qryPartParam.setPartName("TCL");
//qryPartParam.setSalePriceLow(0f);
//qryPartParam.setSalePriceHigh(10000f); List<PartInfo> partInfos = selectPartByUser(qryPartParam);
if (partInfos != null) {
for (PartInfo partInfo : partInfos) {
System.out.println("ID:"+partInfo.getId()+" 商品:["+
partInfo.getPartCode()+"] "+
partInfo.getPartName()+" ,售价:"+
partInfo.getSalePrice()+"元/"+
partInfo.getUnit());
}
}

执行,我们会发现打印出来的结果是空的。为什么会查询不到数据呢?我们跟踪一下SQL执行记录会发现最终生成的SQL语句为:

SELECT * FROM tbInfoPart WHERE PartCode='001-0001' AND PartName LIKE '%'+null+'%' AND SalePrice>=null AND SalePrice<=null

为了避免出现这种情况,我们就需要修改PartMapper文件:

<select id="getPartInfoByUser" parameterType="com.mybatis.entity.QryPartParam" resultType="com.mybatis.entity.PartInfo">
SELECT * FROM tbInfoPart WHERE 1=1
<if test="partCode != null">AND PartCode = #{partCode}</if>
<if test="partName != null">AND PartName LIKE '%'+#{partName}+'%'</if>
<if test="salePriceLow != null">AND SalePrice <![CDATA[>=]]> #{salePriceLow}</if>
<if test="salePriceHigh != null">AND SalePrice <![CDATA[<=]]> #{salePriceHigh}</if>
</select>

Mybatis中if为判断标签,如果test的内容成立,则标签内容会最终编译为SQL语句。注意test判断内容中的“partCode”、“partName”等来源于parameterType的值,本例来源:com.mybatis.entity.QryPartParam的属性列表。

也可以这样:

<select id="getPartInfoByUser" parameterType="com.mybatis.entity.QryPartParam" resultType="com.mybatis.entity.PartInfo">
SELECT * FROM tbInfoPart
<where>
<if test="partCode != null">AND PartCode = #{partCode}</if>
<if test="partName != null">AND PartName LIKE '%'+#{partName}+'%'</if>
<if test="salePriceLow != null">AND SalePrice <![CDATA[>=]]> #{salePriceLow}</if>
<if test="salePriceHigh != null">AND SalePrice <![CDATA[<=]]> #{salePriceHigh}</if>
</where>
</select>

where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。

经过本次改动后就可以正常的查询到商品信息了。

3. 关于更新商品信息的疑问

Mybatis实现增删改查(二)中我们实现了对商品信息的编辑,我们再仔细看一下当时main的方法:

public static void main(String[] args) {
PartInfo partInfo;
//查询ID=1的商品并赋值给partInfo
partInfo = selectPart(1);
System.out.println("原商品信息:["+partInfo.getPartCode()+"] "+
partInfo.getPartName()+" ,售价:"+
partInfo.getSalePrice()+"元/"+
partInfo.getUnit()); //调整该商品的各项属性
partInfo.setPartCode("001-0003");
partInfo.setPartName("康佳(KONKA) LED55U60 55英寸 优酷电视梦想版8核优酷视频海量应用");
partInfo.setUnit("台");
partInfo.setSalePrice(2999.00f);
//将新商品保存至数据库
updatePart(partInfo);
System.out.println("修改商品完成!");
//重新查看并展示ID=1的商品
partInfo = selectPart(1);
System.out.println("新商品信息:["+partInfo.getPartCode()+"] "+
partInfo.getPartName()+" ,售价:"+
partInfo.getSalePrice()+"元/"+
partInfo.getUnit());
}

在上面的代码里,我们先查询出ID=1的商品并赋值给partInfo实例,然后针对partInfo进行了修改并保存,然后重新查询ID=1的商品看了看结果确实是我们想要的效果。但是在实际开发中大部分不是这样:当前端页面向我们请求ID=1的商品信息的时候,我们查询出ID=1的商品并赋值给partInfo实例,然后将partInfo序列化为Json串返回给前端,假设前端页面只能编辑“商品编码”、“商品名称”、“单位”,不能修改也不能展示商品的售价,即前端页面中的Form表单就没有绑定SalePrice,那么当用户做完想要的修改点击保存,然后提交给后台的Json再经过我们的反序列化生成的实例partInfo的salePrice属性会为null,这种情况下我们通过Mybatis执行保存后会发生什么呢?

我们重新修改下main方法测试一下:

public static void main(String[] args) {
//查看并展示ID=1的商品
PartInfo partInfoOld = selectPart(1);
System.out.println("ID:"+partInfoOld.getID()+" 原商品信息:["+
partInfoOld.getPartCode()+"] "+
partInfoOld.getPartName()+",售价:"+
partInfoOld.getSalePrice()+"元/"+
partInfoOld.getUnit());
//模拟前端返回来Json后我们反序列化的实例,注意没有为salePrice赋值
PartInfo partInfo = new PartInfo();
partInfo.setID(1);
partInfo.setPartCode("001-0003");
partInfo.setPartName("康佳(KONKA) LED55U60 55英寸 优酷电视梦想版8核优酷视频海量应用");
partInfo.setUnit("台");
//将商品保存至数据库
updatePart(partInfo);
System.out.println("修改商品完成!");
//重新查看并展示ID=1的商品
PartInfo partInfoNew = selectPart(1);
System.out.println("ID:"+partInfoNew.getID()+" 新商品信息:["+
partInfoNew.getPartCode()+"] "+
partInfoNew.getPartName()+" ,售价:"+
partInfoNew.getSalePrice()+"元/"+
partInfoNew.getUnit());
}

执行main方法后的打印结果为:

ID: 新商品信息:[-] 康佳(KONKA) LED55U60 55英寸 优酷电视梦想版8核优酷视频海量应用,售价:.90元/台
修改商品完成!
ID: 新商品信息:[-] 康佳(KONKA) LED55U60 55英寸 优酷电视梦想版8核优酷视频海量应用,售价:null元/台

我们发现商品的SalePrice被更新成了null,然后我们跟踪Mybaits编译出来的SQL脚本为:

UPDATE tbInfoPart SET
PartCode='001-0003',
PartName='康佳(KONKA) LED55U60 55英寸 优酷电视梦想版8核优酷视频海量应用',
Unit='台',
SalePrice=null
WHERE ID=1

为了避免为null的属性被更新到数据库里面我们可以如下调整PartMapper:

<!-- #{} 大括号里面的参数名是和com.mybatis.entity.PartInfo中的属性名对应的 -->
<!-- mybatis会自动将其属性值按照数据类型填充到被预编译的SQL脚本中 -->
<update id="updatePartInfo" parameterType="com.mybatis.entity.PartInfo">
UPDATE tbInfoPart SET
<if test="partCode != null">PartCode=#{partCode},</if>
<if test="partName != null">PartName=#{partName},</if>
<if test="unit != null">Unit=#{unit},</if>
<if test="salePrice != null">SalePrice=#{salePrice}</if>
WHERE ID=#{id}
</update>

但是这样依然会报错,因为这种情况最终生成的SQL为:

UPDATE tbInfoPart SET
PartCode='001-0003',
PartName='康佳(KONKA) LED55U60 55英寸 优酷电视梦想版8核优酷视频海量应用',
Unit='台',
WHERE ID=1

最终生成的SQL在WHERE之前多了一个逗号。为了避免这种情况,我们可以使用Mybatis的trim标签。最终的PartMapper修改结果如下:

<!-- #{} 大括号里面的参数名是和com.mybatis.entity.PartInfo中的属性名对应的 -->
<!-- mybatis会自动将其属性值按照数据类型填充到被预编译的SQL脚本中 -->
<update id="updatePartInfo" parameterType="com.mybatis.entity.PartInfo">
UPDATE tbInfoPart SET
<trim prefix="" suffix="" prefixOverrides="" suffixOverrides=",">
<if test="partCode != null">PartCode=#{partCode},</if>
<if test="partName != null">PartName=#{partName},</if>
<if test="unit != null">Unit=#{unit},</if>
<if test="salePrice != null">SalePrice=#{salePrice},</if>
</trim>
WHERE ID=#{id}
</update>

trim标签的属性

1.prefix:前缀覆盖并增加其内容

2.suffix:后缀覆盖并增加其内容

3.prefixOverrides:前缀判断的条件

4.suffixOverrides:后缀判断的条件

即trim标签中编译出的SQL字符串,如果是以prefixOverrides设定的值开头,则会被替换成prefix设定的值。如果是以suffixOverrides设定的值结尾则会被替换成suffix设定的值。

也可以这样:

<!-- #{} 大括号里面的参数名是和com.mybatis.entity.PartInfo中的属性名对应的 -->
<!-- mybatis会自动将其属性值按照数据类型填充到被预编译的SQL脚本中 -->
<update id="updatePartInfo" parameterType="com.mybatis.entity.PartInfo">
UPDATE tbInfoPart
<set>
<if test="partCode != null">PartCode=#{partCode},</if>
<if test="partName != null">PartName=#{partName},</if>
<if test="unit != null">Unit=#{unit},</if>
<if test="salePrice != null">SalePrice=#{salePrice},</if>
</set>
WHERE ID=#{id}
</update>

set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。

这样我们就可以灵活的更改商品的任意属性而不用顾忌其他属性是否为null了。

4. 目录结构

Mybatis实现if trim(四)的更多相关文章

  1. Springboot & Mybatis 构建restful 服务四

    Springboot & Mybatis 构建restful 服务四 1 前置条件 成功执行完Springboot & Mybatis 构建restful 服务三 2 restful ...

  2. MyBatis基础入门《四》接口方式.Select查询集合

    MyBatis基础入门<四>接口方式.Select查询集合 描述: 在<MyBatis基础入门<二>Select查询>中有说过,SQLSession有两种用法,这里 ...

  3. Mybatis 实用篇(四)返回值类型

    Mybatis 实用篇(四)返回值类型 一.返回 List.Map List<User> getUsers(); <select id="getUsers" re ...

  4. MyBatis 3(中文版) 第四章 使用注解配置SQL映射器

    本章将涵盖以下话题: l 在映射器Mapper接口上使用注解 l 映射语句 @Insert,@Update,@Delete,@SeelctStatements l 结果映射 一对一映射 一对多映射 l ...

  5. mybatis 学习笔记(四):mybatis 和 spring 的整合

    mybatis 学习笔记(四):mybatis 和 spring 的整合 尝试一下整合 mybatis 和 spring. 思路 spring通过单例方式管理SqlSessionFactory. sp ...

  6. Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?

    Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的?   如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...

  7. MyBatis学习总结(四)——MyBatis缓存与代码生成

    一.MyBatis缓存 缓存可以提高系统性能,可以加快访问速度,减轻服务器压力,带来更好的用户体验.缓存用空间换时间,好的缓存是缓存命中率高的且数据量小的.缓存是一种非常重要的技术. 1.0.再次封装 ...

  8. mybatis标签之——<trim>及 <foreach collection>

    https://www.cnblogs.com/zjfjava/p/8882614.html trim标记是一个格式化的标记,主要用于拼接sql的条件语句(前缀或后缀的添加或忽略),可以完成set或者 ...

  9. Mybatis学习笔记(四) 之动态SQL语句

    动态SQL mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类: 1. if 语句 (简单的条件 ...

随机推荐

  1. DNS原理和智能DNS及CDN

    CDN是什么 CDN(Content Delivery Network)是内容分发网络. 作用: 使用户可以就近取的所需要的内容,加速用户访问网站资源的速度.物理距离更近,响应速度更快.拦截部分网络请 ...

  2. [LeetCode] 932. Beautiful Array 漂亮数组

    For some fixed N, an array A is beautiful if it is a permutation of the integers 1, 2, ..., N, such ...

  3. ICE使用记录

    在使用ice中间件的过程中 如果A继承了 ****Disp_类 在使用A类的时候 ****Disp_类会浅表克隆该类出一个新的对象a 在调用重写的接口的时候是使用a 在主动调用A类的对象的时候使用的才 ...

  4. 干货分享:Academic Essay写作套路详解

    你想过如何中立的表达自己吗?大概只有10%不到的同学,会真正重视这个细节.但很多留学生能顺利写完作文已经不容易,还要注意什么中立不中立的.我知道这个标准,对许多同学有些过分,但很残酷的告诉你,这的确是 ...

  5. Windows2008R2安装iis和iis下搭建web服务器(9.18 第七天)

    IIS internet information services 互联网信息服务微软开发的运行在windows中的互联网服务,提供了web.ftp.smtp服务 Windows server 200 ...

  6. hash表系列(转)

    http://www.cnblogs.com/mumuxinfei/p/4441826.html 前言: 我以前在百度的mentor, 在面试时特喜欢考察哈希表. 那时的我满是疑惑和不解, 觉得这东西 ...

  7. 04 Unity2D

    Unity2D系统是Unity引擎进行2D制作时使用的 Sprite精灵:在Unity2D制作中将图片称作精灵(Sprite),为了提高游戏效率,降低对GPU的损耗,通常将一类的图片拼接成一张大图来使 ...

  8. [Python函数]encode,decode

    前言: 我们知道,计算机是以二进制为单位的,也就是说计算机只识别0和1,也就是我们平时在电脑上看到的文字,只有先变成0和1,计算机才会识别它的意思.这种数据和二进制的转换规则就是编码.计算机的发展中, ...

  9. spring boot集成mybatis(2) - 使用pagehelper实现分页

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  10. Windows桌面图标不见了,可能是结束了explorer.exe进程导致

    Windows桌面图标不见了,怎么办?那么可能是你关掉了explorer.exe的进程. 解决办法: ① Ctrl+shift+delete打开任务管理器,查看进程是否有explorer.exe ② ...