文章目录
mybatis的SQL语句动态拼接
mybatis的SQL语句动态拼接学习:
问题:
在学习了Mybatis的Sql动态代理后,我们可以很放方便的实现单表的增删改查。
但是我们又发现,很多时候,根据业务需求,无法事先确定要执行的SQL语句。
用户发起请求的数据不同,需要执行的SQL语句也不同,怎么办呢?
解决:
根据不同的参数的值,动态的拼接SQL语句。
传统方式实现:
在DaoImpl层的代码中使用java逻辑代码,判断接受的参数的值,
动态的拼接SQL语句。
Mybatis方式实现:
因为MyBatis的Sql动态代理方式中,Mapper接口的实现是动态生成的
我们无法在其中书写java逻辑代码实现SQL语句的动态拼接。但是我们
是在mapper.xml文件中声明SQL语句的,所以Mybatis希望我们Mapper
.xml文件中完成对Sql语句的动态拼接。
使用:
Mybatis的mapper配置文件的逻辑标签
常用: if标签
where标签
set标签
foreach标签
bind标签
choose when otherwise标签
trim标签
sql标签
include 标签
总结:
其实就是由我们在自己声明的DaoImpl代码中使用java逻辑代码判断实现SQL动态拼接,变成了
在Mapper.xml文件中使用逻辑标签完成SQL动态拼接的判断,但是本质上是一样的。
if标签
根据花卉名称和花卉产地动态查询花卉信息
if标签
作用:根据方法的参数的值,实现SQL语句的拼接,相当于java的单if
使用:
<if test="">
要拼接的内容
</if>
注意:test可以直接书写逻辑判断,但连接符号为 and 或 or
可以使用param1|键名|属性名|注解别名 获取参数的值
如:test="param1 !='' and param1 != null"
<?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="com.sxt.mapper.FlowerMapper">
<select id="query" resultType="flower">
SELECT * FROM flower
<if test="param1 !='' and param1 != null">
WHERE name=#{param1}
</if>
</select>
<select id="query2" resultType="flower">
SELECT * FROM flower WHERE 1=1
<if test="param1 !='' and param1 != null">
and name=#{param1}
</if>
<if test="param2 != '' and param2 != null">
and production=#{param2}
</if>
</select>
//if标签
List<Flower> query(String name,String production);
List<Flower> query2(String name,String production);
测试
public class FlowerTest {
private SqlSession session;
private FlowerMapper flower;
@Before //在所有@Test注解执行之前 执行
public void before() throws IOException{
InputStream in = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
//getMapper():动态代理 传过去一个接口,返回一个代理对象
flower = session.getMapper(FlowerMapper.class);
}
@After
public void After(){
session.commit();
session.close();
}
@Test
public void test1(){
List<Flower> u = flower.query("牵牛花", "阿根廷");
for(Flower us:u){
System.out.println(us);
}
}
@Test
public void test2(){
List<Flower> u = flower.query2("", "");
for(Flower us:u){
System.out.println(us);
}
}
where标签
根据花卉名称和花卉产地动态查询花卉信息
where标签
作用:如果被包含的内容有任意一个成立,则自动生成where关键字
自动去除被包含内容的第一个and或or关键字
使用:
<where>
内容(可以是其他的标签,最常用的是if标签和choose标签)
</where>
<select id="where" resultType="flower">
SELECT * FROM flower
<where>
<if test="param1 !='' and param1 != null">
and name=#{param1}
</if>
<if test="param2 != '' and param2 != null">
and production=#{param2}
</if>
</where>
</select>
//where标签
List<Flower> where(String name,String production);
@Test
public void test3(){
List<Flower> u = flower.where("", "雪里");
for(Flower us:u){
System.out.println(us);
}
}
set标签
修改花卉信息
set标签
作用:生成一个set关键字,并去除内容的最后一个逗号。
使用:在update语句中使用,实现动态更新
<update id="up">
UPDATE flower
<set>
id=#{param3},
<if test="param1 !='' and param1 != null">
name=#{param1},
</if>
<if test="param2 != '' and param2 != null">
production=#{param2}
</if>
</set>
WHERE id=#{param3}
</update>
//set标签
int up(String name,String production,Integer id);
@Test
public void test5(){
int up = flower.up("", "阿根廷2", 1);
System.out.println(flower);
}
foreach标签
根据ID动态查询花卉信息
foreach循环标签:
作用:结合 IN 关键字,实现 IN语句中的数据的动态拼接 , 可以实现多选的动态删除
属性: collection: list | array
声明遍历的是list集合还是数组,list和array为底层map集合的键名
item:当次遍历的数据
open:遍历所有的结果内容之前要拼接的符号
close:遍历所有的结果内容之后要拼接的
separator:内容的间隔符号
<select id="selByIdAll" resultType="flower">
SELECT * FROM flower WHERE id IN
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
<select id="selByIdAlls" resultType="flower">
SELECT * FROM flower WHERE id IN
<foreach collection="array" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
//foreach循环标签
List<Flower> selByIdAll(List ls);
List<Flower> selByIdAlls(String[] str);
@Test
public void test7(){
List<Integer> ls = new ArrayList<>();
ls.add(1);
ls.add(2);
ls.add(3);
List<Flower> list = flower.selByIdAll(ls);
System.out.println("foreach:"+list);
String[] str = {"1","2","3"};
flower.selByIdAlls(str);
System.out.println("foreachArray:"+str);
}
bind标签
根据花卉名称模糊查询
bind标签
作用:给接受的实参重新拼接赋值,一般 like语句中使用
属性: name:新的键名
value:实参和符合的拼接语句
注意:实参的获取底层会调用get方法获取,需要我们使用注解别名,或者对象封装
<select id="selBind" resultType="flower">
<!-- 使用bind 标签 -->
<bind name="pm" value="'%'+name+'%'"/>
SELECT * FROM flower WHERE name LIKE #{pm}
</select>
//bind标签
List<Flower> selBind(@Param("name")String name);
@Test
public void test8(){
List<Flower> bi = flower.selBind("花");
System.out.println("bind标签: "+bi);
List<Flower> bi2 = flower.selBind("草");
System.out.println("bind标签: "+bi2);
}
choose | when | otherwise标签
根据花卉名称和花卉产地动态查询花卉信息
choose | when | otherwise标签
作用:判断参数的值,拼接不同的SQL语句。类似java中的多分支语句
注意:此结构只能成立一个条件,只要成立一个条件,其他就不会判断执行了
<select id="selChoose" resultType="flower">
SELECT * FROM flower
<where>
<choose>
<when test="param1 != '' and param1 != null">
AND name=#{param1}
</when>
<when test="param2 != '' and param2 != null">
AND production=#{param2}
</when>
<otherwise>
AND 1=1
</otherwise>
</choose>
</where>
</select>
//choose | when | otherwise标签
List<Flower> selChoose(String name,String production);
@Test
public void test4(){
List<Flower> u = flower.selChoose("", "");
for(Flower us:u){
System.out.println(us);
}
}
trim标签
修改花卉信息
trim标签
作用:给指定的内容 添加或去除 前后缀信息
属性: prefix:给原有内容添加指定的前缀
prefixOverrides:去除原有内容的指定前缀
suffix:给原有内容添加指定的后缀
suffixOverrides:去除原有内容的指定后缀
<update id="upTrim">
UPDATE flower
<trim prefix="set" suffixOverrides=",">
id=#{param3},
<if test="param1 != '' and param1 != null">
name=#{param1},
</if>
<if test="param2 != '' and param2 != null">
production=#{param2}
</if>
</trim>
WHERE id=#{param3}
</update>
//trim标签
int upTrim(String name,String production,Integer id);
sql标签和include标签
查询所有花卉信息
sql标签和include标签
作用:降低不同的select子句中的字段名的冗余
使用: 使用SQL标签声明select子句的公共查询字段
然后使用include标签在select子句中引入公共字段声明
<select id="selAll" resultType="flower">
SELECT id,name,<include refid="my"></include>FROM flower
</select>
<sql id="my">
price,production
</sql>
</mapper>
//sql标签和include标签
List<Flower> selAll();
@Test
public void test9(){
List<Flower> all = flower.selAll();
System.out.println(" "+all);
}
}