MyBatis中的动态SQL语句
2020-08-09 本文已影响0人
凡哥爱丽姐
项目配置给上一章的模糊查询一样,并根据上一章内容讲解本节内容,上一章中我们讲解了三种模糊查询都是多条件查询,若我们要查询含‘张’字的所有用户,不指定性别,则会出现什么情况呢?
import com.fan.dao.UserDao;
import com.fan.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
try {
Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSession sqlSession = new SqlSessionFactoryBuilder().build(resourceAsReader).openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> users = mapper.findByNameAndSex("张", null);
for (User user:users) {
System.out.println(user);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果如下图所示:

通过运行结果发现,查询出来的用户列表为空,在MySQL数据库中执行该SQL语句,查询结果确实为空。但根据正常的逻辑思考,在用户没有输入用户性别的情况下,只根据名称进行模糊查询,结果应该是所有name中含“孙”的用户信息。
1、解决方案是使用动态SQL的if元素来实现多条件查询
1.1、修改配置文件UserDaoMapper.xml
<mapper namespace="com.fan.dao.UserDao">
<select id="findByNameAndSex" resultType="com.fan.entity.User">
select * from users where
<if test="uname!=null">
name like "%"#{uname}"%"
</if>
<if test="usex!=null">
and sex=#{usex}
</if>
</select>
</mapper>
1.2、测试类
import com.fan.dao.UserDao;
import com.fan.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
try {
Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSession sqlSession = new SqlSessionFactoryBuilder().build(resourceAsReader).openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> users = mapper.findByNameAndSex("张", null);
for (User user:users) {
System.out.println(user);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果如下图所示:

通过运行结果发现,通过动态SQL语句,只根据名称进行模糊查询,结果可以显示所有name中含“孙”的用户信息。
若现在我们要找出性别为“男”的用户,直接修改上述的测试类,会实现该要求吗?
List<User> users = mapper.findByNameAndSex(null, "男");
测试结果如下图所示:

我们可以发现SQL语句出现了错误,即where子句后面多了一个“and”,那么我们可以通过下述方法去解决该问题
2、解决方案
2.1、方案1
2.1.1、修改配置文件UserDaoMapper.xml中的SQL语句
<mapper namespace="com.fan.dao.UserDao">
<select id="findByNameAndSex" resultType="com.fan.entity.User">
select * from users where 1=1
<if test="uname!=null and uname!=''">
and name like "%"#{uname}"%"
</if>
<if test="usex!=null">
and sex=#{usex}
</if>
</select>
</mapper>
2.1.2、测试类
import com.fan.dao.UserDao;
import com.fan.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
try {
Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSession sqlSession = new SqlSessionFactoryBuilder().build(resourceAsReader).openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> users = mapper.findByNameAndSex(null, "男");
for (User user:users) {
System.out.println(user);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果如下图所示:
测试结果
2.2、方案2
2.2.1、修改配置文件UserDaoMapper.xml中的SQL语句
<mapper namespace="com.fan.dao.UserDao">
<select id="findByNameAndSex" resultType="com.fan.entity.User">
select * from users
<where>
<if test="uname!=null and uname!=''">
and name like "%"#{uname}"%"
</if>
<if test="usex!=null">
and sex=#{usex}
</if>
</where>
</select>
</mapper>
2.2.2、测试类
import com.fan.dao.UserDao;
import com.fan.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
try {
Reader resourceAsReader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSession sqlSession = new SqlSessionFactoryBuilder().build(resourceAsReader).openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> users = mapper.findByNameAndSex(null, "男");
for (User user:users) {
System.out.println(user);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果如下图所示:

注:上述代码中,where元素标签会自动识别其标签内是否有返回值,若有,就插入一个where。此外,若标签返回的内容是以and或者or开头的,会自动剔除。
3、if+trim用法
在MyBatis中,除了使用if+where实现多条件查询,还有一个更为灵活的元素trim可以替代之前的做法。
trim元素也会自动识别其他标签内是否有返回值,则在自己包含的内容前面加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;trim也可以把包含内容的首部的某些内容覆盖(即忽略),或者把尾部的某些内容覆盖,与之对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样强大的功能,我们才可以利用trim来替代where元素,并实现与where元素相同的效果,接下来就改造上一个示例来实现多用户查询操作。
<mapper namespace="com.fan.dao.UserDao">
<select id="findByNameAndSex" resultType="com.fan.entity.User">
select * from users
<trim prefix="where" prefixOverrides="and|or">
<if test="uname!=null and uname!=''">
and name like "%"#{uname}"%"
</if>
<if test="usex!=null">
and sex=#{usex}
</if>
</trim>
</select>
</mapper>