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. 剑指offer自学系列(四)

    题目描述: 输入一个正整数数组,把数组里面所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个,例如输入数组{3,32,321},输出的最小数字为321323 题目分析: 如果采用穷举法,把 ...

  2. Q 格式使用总结

    注意 16位有符号数 表示的范围是 -32768~32767 假如 整形数在内存中以源码的形式存放, 则0000 0000 0000 0000 表示正整数0 则 1000 0000 0000 0000 ...

  3. springboot启动微服务项目时,启动后没有端口号信息,也访问不了

    2018-06-05 13:43:42.282 [localhost-startStop-1] DEBUG org.apache.catalina.core.ContainerBase - Add c ...

  4. tomcat启动报错The JRE could not be found.Edit the server and change the JRE location

    解决: 在Windows->Preferences->Server->Runtime Environments 选择Tomcat->Edit,在jre中选择相应的jdk版本,完 ...

  5. swift中数据之间的转换

    1.swift 开发 - NSDictionary与NSData互转.Dictionary与Data互转 https://blog.csdn.net/SuperMageHuang/article/de ...

  6. ubuntu12.04 安装完XRDP显示空白桌面

    先放链接:http://c-nergy.be/blog/?p=3518 在ubuntu软件中心搜索:fallback session,安装gnome-session-fallback: 在主文件夹(h ...

  7. 打包APK出现org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:lintVitalRelease'.

    AndroidS Studio打包APK时出现问题:org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':a ...

  8. Spark SQL 笔记

    Spark SQL 简介 SparkSQL 的前身是 Shark, SparkSQL 产生的根本原因是其完全脱离了 Hive 的限制.(Shark 底层依赖于 Hive 的解析器, 查询优化器) Sp ...

  9. springboot项目 线程消费队列注入报错误空指针

    背景: 在调用阿里云隐私保护有一个通话记录的回执消息是一个消费线程队列,这个还别人告诉我的,因为我根本没有看出来哪里是个线程了,然后我就把它当成普通的代码拿到返回值以后然后插入数据库 可是我这边该加的 ...

  10. java的JDBC的事务学习

    https://www.cnblogs.com/chy18883701161/p/11372089.html