mybatis中的动态SQL
场景介绍
如果只是简单的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
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
