笔记53 Mybatis快速入门(四)
动态SQL
1.if
假设需要对Product执行两条sql语句,一个是查询所有,一个是根据名称模糊查询。那么按照现在的方式,必须提供两条sql语句:listProduct和listProductByName然后在调用的时候,分别调用它们来执行。如下所示:
Product.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mybatis.pojo"> <select id="listProduct1" resultType="Product">
select * from product
</select>
<select id="listProductByName" resultType="Product">
select *
from product where name like concat('%',#{name},'%')
</select>
</mapper>
Test.java
package mybatis.test; import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import mybatis.pojo.Product; public class testIf {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = org.apache.ibatis.io.Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession(); System.out.println("查询所有的");
List<Product> products = session.selectList("listProduct1");
for (Product product : products) {
System.out.println(product);
} System.out.println("模糊查询");
Map<String, Object> params = new HashMap<String, Object>();
params.put("name", "a");
List<Product> products2 = session.selectList("listProductByName",
params);
for (Product product : products2) {
System.out.println(product);
} session.commit();
session.close();
}
}

如果Product的字段比较多的话,为了应付各个字段的查询,那么就需要写多条sql语句,这样就变得难以维护。这个时候,就可以使用Mybatis 动态SQL里的if标签
<select id="listProduct2" resultType="Product">
select * from product
<if test="name!=null">
where name like concat('%',#{name},'%')
</if>
</select>
如果没有传参数name,那么就查询所有,如果有name参数,那么就进行模糊查询。这样只需要定义一条sql语句即可应付多种情况了,在测试的时候,也只需要调用这么一条sql语句listProduct 即可。
System.out.println("查询所有的");
List<Product> products = session.selectList("listProduct2");
for (Product product : products) {
System.out.println(product);
}
System.out.println("模糊查询");
Map<String, Object> params = new HashMap<String, Object>();
params.put("name", "a");
List<Product> products2 = session.selectList("listProduct2", params);
for (Product product : products2) {
System.out.println(product);
}
2.where
<1>如果要进行多条件判断,如下所示:
<select id="listProduct2" resultType="Product">
select * from product
<if test="name!=null">
where name like concat('%',#{name},'%')
</if>
<if test="price!=0">
and price>=#{price}
</if>
</select>
System.out.println("多条件查询");
Map<String, Object> params = new HashMap<String, Object>();
params.put("name", "a");
params.put("price", "10");
List<Product> products2 = session.selectList("listProduct4", params);
for (Product product : products2) {
System.out.println(product);
}
这么写的问题是:当没有name参数,却有price参数的时候,执行的sql语句就会是:select * from product_ and price > 10。这样就会报错。
这个问题可以通过<where>标签来解决,如代码所示:
<select id="listProduct4" resultType="Product">
select * from product
<where>
<if test="name!=null">
and name like concat('%',#{name},'%')
</if>
<if test="price!=null and price!=0">
and price>#{price}
</if>
</where>
</select>
<where>标签会进行自动判断:
如果任何条件都不成立,那么就在sql语句里就不会出现where关键字
如果有任何条件成立,会自动去掉多出来的 and 或者 or。
所以map里面两个参数无论是否提供值都可以正常执行。
<2>与where标签类似的,在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:
<update id="updateProduct" parameterType="Product">
update product
<set>
<if test="name!=null">name=#{name},</if>
<if test="price!=null">price=#{price}</if>
</set>
where id=#{id}
</update>
Product product = new Product();
product.setId(6);
product.setName("product xzz");
product.setPrice(6.99f);
session.update("updateProduct", product);
<3>trim 用来定制想要的功能,比如where标签就可以用以下代码替换:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
set标签可以用以下代码来替换:
<trim prefix="SET" suffixOverrides=",">
...
</trim>
示例:
<select id="listProduct5" resultType="Product">
select * from product
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="name!=null">
and name like concat('%',#{name},'%')
</if>
<if test="price!=null and price!=0">
and price>#{price}
</if>
</trim>
</select>
<update id="updateProduct2" parameterType="Product">
update product
<trim prefix="SET" suffixOverrides=",">
<if test="name!=null">name=#{name},</if>
<if test="price!=null">price=#{price}</if>
</trim>
where id=#{id}
</update>
3.choose
Mybatis里面没有else标签,但是可以使用when otherwise标签来达到这样的效果。
<select id="listProduct6" resultType="Product">
select * from product
<where>
<choose>
<when test="name!=null">
and name like concat('%',#{name},'%')
</when>
<when test="price!=null and price!=0">
and price>#{price}
</when>
<otherwise>
and id>1
</otherwise>
</choose>
</where>
</select>
作用: 提供了任何条件,就进行条件查询,否则就使用id>1这个条件。
System.out.println("多条件查询");
Map<String, Object> params = new HashMap<String, Object>();
// params.put("name", "a");
// params.put("price", "10");
List<Product> products2 = session.selectList("listProduct6", params);
for (Product products : products2) {
System.out.println(products);
}
查询结果:

如果去掉注释,提供查询条件,则结果如下:

4.foreach
适用情况如下所示:
<select id="listProduct7" resultType="Product">
select * from product
where id in
<foreach item="item" index="index" collection="list" open="("
separator="," close=")">
#{item}
</foreach>
</select>
collection :collection属性的值有三个分别是list、array、map三种,分别对应的参数类型为:List、数组、map集合
item : 表示在迭代过程中每一个元素的别名
index :表示在迭代过程中每次迭代到的位置(下标)
open :前缀
close :后缀
separator :分隔符,表示迭代时每个元素之间以什么分隔
测试:
List<Integer> idsIntegers = new ArrayList<Integer>();
idsIntegers.add(1);
idsIntegers.add(3);
idsIntegers.add(5); List<Product> products = session.selectList("listProduct7", idsIntegers); for (Product product : products) {
System.out.println(product);
}
结果:

5.bind
bind标签就像是再做一次字符串拼接,方便后续使用。如下所示,在模糊查询的基础上,把模糊查询改为bind标签。
<select id="listProductByName" resultType="Product">
select *
from product
where name like concat('%',#{name},'%')
</select>
<select id="listProductByName2" resultType="Product">
<bind name="likename" value="'%'+name+'%'"/>
select *
from product
where name like #{likename}
</select>
笔记53 Mybatis快速入门(四)的更多相关文章
- MyBatis学习笔记(一)——MyBatis快速入门
转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4261895.html 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优 ...
- 笔记56 Mybatis快速入门(七)
相关概念介绍(二) 6.一级缓存 <1>在一个session里查询相同id的数据 package mybatis.annotation; import java.io.IOExceptio ...
- 笔记50 Mybatis快速入门(一)
一.Mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- mybatis快速入门(四)
mybatis动态标签<where><if><foreach>以及sql片段 1.创建一个包装类UserQueryVo.java package cn.my.myb ...
- 笔记55 Mybatis快速入门(六)
相关概念介绍(一) 1.日志 有时候需要打印日志,知道mybatis执行了什么样的SQL语句,以便进行调试.这时,就需要开启日志,而mybatis自身是没有带日志的,使用的都是第三方日志,这里介绍如何 ...
- 笔记54 Mybatis快速入门(五)
Mybatis中注解的使用 1.XML方式的CRUD 新增加接口CategoryMapper ,并在接口中声明的方法上,加上注解对比配置文件Category.xml,其实就是把SQL语句从XML挪到了 ...
- 笔记52 Mybatis快速入门(三)
一.更多查询 1.模糊查询 修改Category.xml,提供listCategoryByName查询语句select * from category where name like concat(' ...
- 笔记51 Mybatis快速入门(二)
Mybatis的CRUD 1.修改配置文件Category.xml,提供CRUD对应的sql语句. <?xml version="1.0" encoding="UT ...
- MyBatis学习总结(一)——MyBatis快速入门
一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...
随机推荐
- 在Ubuntu中安装配置java后运行java -version时提示二进制文件不能执行
因为jdk安装包有问题,试试32位的
- PAT程序设计
VS2013中自行对齐的快捷键操作: CTRL+K+F 1.定义二维数组 ]=]; 2.绝对值函数 int abs(int i) 返回整型参数i的绝对值 double cabs(struct comp ...
- 自定义input[type="radio"]
对于表单,input[type="radio"] 的样式总是不那么友好,在不同的浏览器中表现不一. 对单选按钮自定义样式,我们以前一直用的脚本来实现,不过现在可以使用新的伪类 :c ...
- BUUCTF MISC部分题目wp
MISC这里是平台上比较简单的misc,都放在一起,难一些的会单独写1,二维码图片里藏了一个压缩包,用binwalk -e分离,提示密码为4个数字,fcrackzip -b -c1 -l 4 -u 得 ...
- 记录java ftp下载图片只有96KB的问题
public InputStream downloadFile(String path) { if(StringUtils.isBlank(path)) { return null; } connne ...
- winform程序登陆后关闭登录窗体
用winform做程序的时候,我们一般都是在Program先启动登录窗体,然后登录成功后才创建主窗体,结果这就导致了登录窗体无法关闭 所以如果我们不在Program的程序入口先创建登录窗体的话就能完美 ...
- PHP-在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n) 级别. 如果数组中不存在目标值,返回 [ ...
- 【leetcode】965. Univalued Binary Tree
题目如下: A binary tree is univalued if every node in the tree has the same value. Return true if and on ...
- leetcode-161周赛-1250-检查好数组
题目描述: 唯一的结论是如果数组中所有数的最大公约数为 1,则存在解,否则不存在.所以只需要计算所有数最大公约数即可,时间复杂度O(nlog(m)),其中 m 为数字大小. class Solutio ...
- 6371. 【NOIP2019模拟2019.9.28】基础图论练习题
题目 题目大意 维护一个无向图的割边条数,支持加边和删边. 正解 (PS:这是我很久之前在OJ上打出来的题解,现在直接copy过来) 题解只有一句话,估计没多少人可以看得懂.感觉出题人偷懒不想写题解- ...