动态SQL
开发人员通常根据需求手动拼接SQL语句,这是一个极其麻烦的事情,而且很容易出错。MyBatis提供了动态组装的功能,允许在SQL语句中加入 <if>、<where>、<when>、<foreach>
用于逻辑控制的元素,达到SQL语句根据需要动态变化的效果。
我们重新创建一个UserMapperDanmic接口和UserMapperDanmic.xml文件,专门讲解动态SQL语句
- UserMapperDanmic接口
public interface UserMapperDanmic {
/*此处添加和SQL语句对应的抽象方法*/
}
- UserMapperDanmic.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="com.itheima.mapper.UserMapperDanmic">
<!--此处填写SQL语句-->
</mapper>
<if>语句
在UserMapperDanmic接口中添加下面的抽象方法
//根据条件动态查询用户信息
public List<User> selectUserByIf(User user);
在UserMapperDanmic.xml映射文件中,添加下面的代码,根据条件动态查询用户信息
<!--根据条件动态的查询用户信息-->
<!--where后面的1=1,是为了防止后面的if都不满足时,sql语句不成立而特加的-->
<!--*if test用于判断-->
<select id="selectUserByIf" resultType="com.itheima.domain.User" parameterType="user">
select * from user where 1=1
<if test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
<if test="usex!=null and usex!=''">
and usex=#{usex}
</if>
</select>
创建UserMapperDanmicTest测试类,编写测试方法,代码如下
@Test
public void test(){
InputStream in = null;
try {
//读取配置文件
in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(in);
SqlSession ss = ssf.openSession();
//获取映射器接口
UserMapperDanmic mapper = ss.getMapper(UserMapperDanmic.class);
//创建参数对象,查询姓王的男性用户的信息
User user=new User();
user.setUname("王"); //注释掉试试
user.setUsex("男"); //注释掉试试
List<User> list = mapper.selectUserByIf(user);
for (User u : list) {
System.out.println(u);
}
} catch (IOException e) {
e.printStackTrace();
}
}
运行测试方法test会方法,查看日志信息,其查询语句是这样的
select * from user where 1=1 and uname like concat('%',?,'%') and usex=?
把user.setUname
注释掉再运行,查看日志信息,其查询语句是这样的
select * from user where 1=1 and usex=?
把user.setUsex
注释掉再运行,查看日志信息,其查询语句是这样的
select * from user where 1=1 and uname like concat('%',?,'%')
把user.setUname和user.setUsex
都注释掉,查看日志信息,其查询语句是这样的
select * from user where 1=1
<choose>语句
choose语句类似于Java的switch语句,用户从几个条件语句中进行选择执行
现在UserMapperDanmic接口中添加下面的抽象方法
//根据条件动态查询用户信息
public List<User> selectUserByChoose(User user);
再到UserMapperDanmic映射文件中添加下面的代码
<!--使用choose、when、otherwise元素动态的查询用户信息-->
<!--类似于switch、case、default-->
<select id="selectUserByChoose" parameterType="user" resultType="user">
select * from user where 1=1
<choose>
<when test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</when>
<when test="usex!=null and usex!=''">
and usex=#{usex}
</when>
<otherwise>
and id>=10
</otherwise>
</choose>
</select>
在UserMapperDanmicTest测试类中编写测试方法,代码如下
@Test
public void test2(){
InputStream in = null;
try {
//读取配置文件
in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(in);
SqlSession ss = ssf.openSession();
//获取映射器接口
UserMapperDanmic mapper = ss.getMapper(UserMapperDanmic.class);
//创建参数对象
User user=new User();
user.setUname("王"); //注释掉试试
user.setUsex("男"); //注释掉试试
List<User> list = mapper.selectUserByChoose(user);
for (User u : list) {
System.out.println(u);
}
} catch (IOException e) {
e.printStackTrace();
}
}
<foreach>语句
<foreach>语句主要用于in条件下,在SQL语句中表示遍历一个集合
先在UserMapperDanmic接口中添加下面的方法
/*查询满足多个id的用户信息*/
public List<User> selectUserByForeach(List<Integer> list);
再到UserMapperDanmic.xml映射文件中添加如下的SQL映射语句
<!--使用foreach语句查询多个id的用户信息-->
<select id="selectUserByForeach" parameterType="List" resultType="user">
select * from user where id in
<foreach collection="list" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</select>
collection: 表示要遍历的集合
item: 表示集合中的元素
index: 表示索引
open: 表示条件以"("开始
speartor: 表示用元素","隔开
close: 表示条件以")"结束
<where>语句
<where>语句用于,在条件查询where语句时替换where语句,如下面的代码
现在UserMapperDanmic接口中添加抽象方法
/*查询满足条件的用户信息*/
public List<User> selectUserByWhere(User user);
再到UserMapperDanmic.xml映射文件中添加SQL映射语句
<!--查询满足条件的用户信息-->
<select id="selectUserByWhere" resultType="com.itheima.domain.User" parameterType="user">
select * from user
<where>
<if test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
<if test="usex!=null and usex!=''">
and usex=#{usex}
</if>
</where>
</select>
再到UserMapperDanmicTest测试类中添加测试方法,进行测试
/*使用where语句查询满足条件的用户信息*/
@Test
public void test4(){
InputStream in = null;
try {
//读取配置文件
in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(in);
SqlSession ss = ssf.openSession();
//获取映射器接口
UserMapperDanmic mapper = ss.getMapper(UserMapperDanmic.class);
//创建User对象
User user=new User();
user.setUname("王");
user.setUsex("男");
List<User> list = mapper.selectUserByWhere(user);
for (User u : list) {
System.out.println(u);
}
} catch (IOException e) {
e.printStackTrace();
}
}
<bind>语句
在进行模糊查询时,不同的数据库字符串拼接函数或者连接符不同,例如MySQL用concat函数、Oracle使用||
连接符,这样MyBatis就需要对不同的数据库进行不同的实现,不利于代码移植。 <bind>
语句就是用来解决这个问题
先在UserMapperDanmic接口中添加抽象方法
/*查询满足条件的用户信息*/
public List<User> selectUserByBind(User user);
再到UserMapperDanmic.xml映射文件中添加SQL映射语句
<!--使用bind语句实现模糊查询-->
<!--bind标签用来 定义模糊查询的条件-->
<select id="selectUserByBind" resultType="user" parameterType="user">
<bind name="uname" value="'%'+uname+'%'"/>
select * from user where uname like #{uname}
</select>
再到UserMapperDanmicTest类中编写测试代码,测试执行
/*使用bind语句模糊查询满足条件的用户信息*/
@Test
public void test5(){
InputStream in = null;
try {
//读取配置文件
in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(in);
SqlSession ss = ssf.openSession();
//获取映射器接口
UserMapperDanmic mapper = ss.getMapper(UserMapperDanmic.class);
//创建User对象
User user=new User();
user.setUname("王");
List<User> list = mapper.selectUserByBind(user);
for (User u : list) {
System.out.println(u);
}
} catch (IOException e) {
e.printStackTrace();
}
}
<sql>语句
<sql>语句用于封装一部分sql语句,以方便在后面的sql语句中复用
抽取sql语句的片段代码如下,分配一个id值
<!--抽取sql语句的片段-->
<sql id="selectUser" select * from User</sql>
在其他的sql语句中根据id,引用前面的sql语句片段
<!--查询指定id指的用户信息-->
<select id="findById" parameterType="int" resultType="user">
<include refid="selectUser"></include> where id=#{id}
</select>
<!--查询满足多个id值的多个用户信息-->
<select id="findByIds" parameterType="list" resultType="user">
<include refid="selectUser"></include>
<where>
<foreach collection="array" open="id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>