目录
一、什么是动态SQL
二、动态sql环境搭建
三、if标签
三、where标签
四、foreach 循环标签
一、什么是动态SQL
动态SQL是一种在运行时根据条件动态生成SQL语句的技术。它允许根据不同的情况构建不同的SQL查询,简单的说就是根据查询条件的不同,生成不同的SQL。
如果有一些业务比较复杂的功能,往往需要拼接SQL,而拼接SQL一不注意,少了引号,空格等格式问题,可能导致错误。为了解决这方面问题,MyBatis使用了动态SQL,通过if, choose, when, otherwise, trim, where, set, foreach
等标签,可组合成非常灵活的SQL
语句,从而在提高SQL
语句的准确性的同时,也大大提高了开发人员的效率。
二、动态sql环境搭建
1.首先创建一个名为user的数据库表。
CREATE TABLE `user` (
`id` varchar(50) NOT NULL COMMENT '用户id',
`user_name` varchar(100) NOT NULL COMMENT '用户名称',
`sex` varchar(3) NOT NULL COMMENT '性别',
`create_date` datetime NOT NULL COMMENT '创建时间',
`age` int(30) NOT NULL COMMENT '年龄'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
2.在项目中创建相对于的实体类
package com.myBatisDemo.pojo;
import lombok.Data;
import java.util.Date;
//实体类
//使用Lombok自动生成无参构造函数和setter/getter、equals、canEqual、hashCode、toString方法
@Data
public class Blog {
private String id;
private String userName;
private String sex;
private Date createDate;
private int age;
}
3.之后再持久层创建对应的Mapper接口,用于编写操作数据库的方法
package com.MyBatisDemo.dao;
import com.atangbiji.pojo.Blog;
public interface UserMapper{
//新增一个博客
int addUSer (User user);
}
4.再项目的resources下创建映射器的配置文件UserMapper.xml,再配置文件中使用标签实现动态SQL语句和映射器函数接口的映射关系。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--命名空间(绑定对应的映射器接口)-->
<mapper namespace="com.myBatisDemo.dao.UserMapper">
<insert id="addUser" parameterType="User">
insert into User(id, user_name, age, create_date, sex)
values (#{id},#{userName},#{age},#{createDate},#{sex});
</insert>
</mapper>
5.之后再项目的test/java目录下测试代码。
import com.atangbiji.pojo.Blog;
import com.atangbiji.utils.IDUtil;
import com.atangbiji.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.Date;
public class MapperTest {
@Test
public void addInitUSer(){
//1、从SqlSessionFactory中获取SqlSession对象
try(SqlSession sqlSession = MyBatisUtils.getSqlSession()){
//2、执行SQL语句
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IDUtil.generateId());
blog.setUserName("张三");
blog.SetGae(20);
blog.setCreateDate(new Date());
blog.setSex("男");
mapper.addUser(blog);
//3、手动提交事务
sqlSession.commit();
}
}
}
三、if标签
语法格式:
<if test="boolean判断结果"> <!--要么为true、要么为false-->
sql语句的部分
</if>
<!-- 对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片段断拼接到其所在的 SQL 语句中。-->
应用实例:
import com.bjpowernode.entity.Student;
import java.util.List;
/**
*
*/
public interface StudentDao {
//if
List<Student> selectIf(Student student);
}
<!-- if
test: 使用对象的属性值作为条件
-->
<select id="selectIf" resultType="com.bjpowernode.entity.Student">
select *
from student
where id=-1
<if test="name!=null and name!=''">
or name=#{name}
</if>
<if test="age>0">
or age=#{age}
</if>
</select>
<!--
<if/>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 id=-1的子句。
因为,若 where 后的所有<if/>条件均为 false,而 where 后若又没有 id=-1 子句,则 SQL 中就会只剩下一个空的 where,SQL 出错。
所以,在where 后,需要添加子句 id=-1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。
-->
@Test
public void testSelectIf() {
SqlSession session = MyBatisUtil.getSqlSession();
StudentDao studentDao=session.getMapper(StudentDao.class);
Student student=new Student();
student.setName("王昭君");
student.setAge(20);
List<Student> students=studentDao.selectIf(student);
students.forEach( stu -> System.out.println("stu === " + stu) );
session.close();
}
上述测试代码执行后的sql语句为:
select *
from student
where id=-1 or name="张起灵" or age=20
三、where标签
语法格式:
<where>
其他动态sql
</where>
应用实例:
<!-- where -->
<select id="selectWhere" resultType="com.bjpowernode.entity.Student">
select *
from student
<where>
<if test="name!=null and name!=''">
or name=#{name}
</if>
<if test="age>0">
or age=#{age}
</if>
</where>
</select>
<!--
使用<where/>标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。
需要注意的是,第一个<if/>标签中的SQL 片断,可以不包含 and。不过,写上 and 也不错,where标签会将离它最近的 and 或者 or 删掉。
但其它<if/>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
-->
@Test
public void testSelectWhere() {
SqlSession session = MyBatisUtil.getSqlSession();
StudentDao studentDao=session.getMapper(StudentDao.class);
Student student=new Student();
student.setName("张三");
student.setAge(20);
List<Student> students=studentDao.selectWhere(student);
students.forEach( stu -> System.out.println("stu === " + stu) );
session.close();
}
经过这次添加where标签后,测试代码之后的sql为;
select *
from student
where id=-1 or name="张起灵" or age=20
四、foreach 循环标签
语法格式:
<foreach collection="集合类型" open="开始的字符" close="结束的字符" item="集合中的成员" separator="集合成员之间的分隔符">
#{item的值}
</foreach>
<!--
如果dao接口中方法的形参是数组,则collection="array"
如果dao接口中方法的形参是List,则collection="list"
#item的值}:获取集合成员的值
-->
应用实例:
import com.bjpowernode.entity.Student;
import java.util.List;
/**
*
*/
public interface StudentDao {
//for-each 1
List<Student> selectForeachOne(List<Integer> idlist);
}
<!-- foreach第一种方式,循环简单类型的List: List<Integer> -->
<select id="selectForeachOne" resultType="com.bjpowernode.entity.Student">
select *
from student
<if test="list!=null and list.size>0">
where id in
<foreach collection="list" open="(" close=")" separator="," item="stuid">
#{stuid}
</foreach>
</if>
</select>
@Test
public void testSelectForeachOne() {
SqlSession session = MyBatisUtil.getSqlSession();
StudentDao studentDao=session.getMapper(StudentDao.class);
List<Integer> idlist=new ArrayList<>();
idlist.add(1001);
idlist.add(1002);
idlist.add(1003);
List<Student> students=studentDao.selectForeachOne(idlist);
students.forEach( stu -> System.out.println("stu === " + stu));
session.close();
}
添加foreach标签后,测试代码之后的sql为;
select *
from student
where id in (1001,1002,1003)
在开发过程中,比较常用的动态SQL标签的格式为:
<sql id="...">
sql语句
</sql>
<include refid="sql标签的id属性值"></include>
<!--
<sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。
而其它标签使用该 SQL 片断,需要使用<include/>子标签。
该<sql/>标签可以定义 SQL 语句中的任何部分,所以<include/>子标签可以放在动态 SQL 的任何位置。
-->
应用实例
import java.util.List;
/**
*
*/
public interface StudentDao {
//代码片段
List<Student> selectSql(List<Student> studentList);
}
<!-- 定义代码片段 -->
<sql id="selectStudent">
select id,name,age from student
</sql>
<sql id="studentFieldList">
where id in
</sql>
<select id="selectSql" resultType="com.bjpowernode.entity.Student">
<include refid="selectStudent"></include>
<if test="list!=null and list.size>0">
<include refid="studentFieldList"></include>
<foreach collection="list" open="(" close=")" separator="," item="student">
#{student.id}
</foreach>
</if>
</select>
@Test
public void testSelectSql() {
SqlSession session = MyBatisUtil.getSqlSession();
StudentDao studentDao=session.getMapper(StudentDao.class);
List<Student> list=new ArrayList<>();
Student s1=new Student();
s1.setId(1001);
Student s2=new Student();
s2.setId(1002);
Student s3=new Student();
s3.setId(1003);
list.add(s1);
list.add(s2);
list.add(s3);
List<Student> students=studentDao.selectSql(list);
students.forEach( stu-> System.out.println("stu === " + stu));
session.close();
}
上述测试代码执行后:
select id,name,age
from student
where id in (1001,1002,1003)
注:喜欢的朋友可以关注公众号“JAVA学习课堂”方便阅读,内容同步更新。