mybatis中的动态SQL

愿天堂没有BUG

共 7539字,需浏览 16分钟

 ·

2021-10-01 13:18

场景介绍

如果只是简单的CRUD, 可能只是需要一个parameterType就可以了, 当然这个接收参数可以是是自定义类型, 也可以是基本数据类型. 可是当传入的参数个数不确定, 或者根据传入的参数是否有值来决定生成什么样的sql语句, 就需要用到mybatis的动态SQL功能了.

项目中用到的xml

mybatis映射表

<?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.raylee.dao.UserMapper">

<!-- sql语句抽取-->
<sql id="selectUser">select * from users</sql>

<!-- 根据条件判断查询操作-->
<select id="findByCondition" resultType="user" parameterType="user">
<include refid="selectUser"></include>
<where>
<if test="id != 0">
id = #{id}
</if>
<if test="username != null">
and username = #{username}
</if>
<if test="password != null">
and password = #{password}
</if>
</where>
</select>

<!-- 根据集合查询数据-->
<select id="findByIds" parameterType="list" resultType="user">
<include refid="selectUser"></include>
<where>
<foreach collection="list" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
</mapper>
复制代码

mybatis配置表

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">


<configuration>
<!-- 自定义别名-->
<typeAliases>
<typeAlias type="com.raylee.domain.User" alias="user"/>
</typeAliases>

<!-- 数据源环境-->
<environments default="developement">
<environment id="developement">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/LCLDataBase"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

<!-- 加载核心配置文件-->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
复制代码

项目中用到的java类

接口

public interface UserMapper {
public List<User> findByCondition(User user);
public List<User> findByIds(List<Integer> ids);
}
复制代码

User类

public class User {
private int id;
private String username;
private String password;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
复制代码

项目中用到的数据库表

动态SQL - if标签

当我们使用普通的select标签进行sql语句查询时, 如果where后面的某个条件为空, 那么造成的后果可能就是查询不到任何结果

mybatis中xml的配置

 <select id="findByCondition" resultType="user" parameterType="user">
     select * from users where username = #{username} and password = #{password}
 </select>
复制代码

调试代码

 InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
 SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
 SqlSession sqlSession = build.openSession(true);
 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
 
 User user = new User();
 user.setId(1);
 user.setUsername("shaosiming");
 //       user.setPassword("123456");
 List<User> userList = mapper.findByCondition2(user);
 System.out.println(userList);
复制代码

生成的sql语句和对应的参数

 select * from users where id = ? and username = ? and password = ?
 1(Integer), shaosiming(String), null
复制代码

执行的结果

预期结果

我们预期是当我们传入的参数有值时, 都会将该条件拼接到where语句后面, 如果没有值, 则不拼接

使用标签来完成这个功能

 <!--    根据条件判断查询操作-->
     <select id="findByCondition" resultType="user" parameterType="user">
         <include refid="selectUser"></include>
         <where>
             <if test="id != 0">
                and id = #{id}
             </if>
             <if test="username != null">
                and username = #{username}
             </if>
             <if test="password != null">
                and password = #{password}
             </if>
         </where>
     </select>
复制代码

使用标签后生成的sql语句和参数

当使用标签后, 如果有空的参数, 则不会将该参数生成到sql语句中

 select * from users WHERE id = ? and username = ?
 1(Integer), shaosiming(String)
复制代码

使用标签后的结果

[User{id=1, username='shaosiming', password='123456'}]

动态SQL - foreach标签

当我们使用in语句要查询多条数据时, 可能需要传入一个集合当作参数, 这里我们需要用到标签

mybatis中xml的配置

 <!--    根据集合查询数据-->
     <select id="findByIds" parameterType="list" resultType="user">
         <include refid="selectUser"></include>
         <where>
             <foreach collection="list" open="id in (" close=")" item="id" separator=",">
                #{id}
             </foreach>
         </where>
     </select>
复制代码

调试代码

 InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
         SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
         SqlSession sqlSession = build.openSession(true);
         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
         
 ArrayList<Integer> ids = new ArrayList<>();
 ids.add(1);
 ids.add(2);
 ids.add(3);
 
 List<User> byIds = mapper.findByIds(ids);
 System.out.println(byIds);
复制代码

生成的sql语句和参数

 select * from users WHERE id in ( ? , ? , ? ) 
 1(Integer), 2(Integer), 3(Integer)
复制代码

执行结果

当前users表中只没有id为3的数据, 因此只查询出来两条

[User{id=1, username='shaosiming', password='123456'}, User{id=2, username='dasiming', password='654321'}]

SQL抽取 - sql标签

 <sql id="selectUser">select * from users</sql>
复制代码

SQL引入 - include标签

 <include refid="selectUser"></include>


作者:云淡风轻的博客
链接:https://juejin.cn/post/7012502938878738440
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



浏览 51
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报