if标签
我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
-
持久层 Dao 接口
/** * 根据用户信息,查询用户列表 * @param user * @return */ List<User> findByUser(User user);
-
持久层 Dao 映射配置
<select id="findByUser" resultType="user" parameterType="user"> select * from user where 1=1 <!-- test中条件关系要写and 不能写&&--> <if test="username!=null and username != '' "> and username like #{username} </if> <if test="address != null"> and address like #{address} </if> </select> 注意: <if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。 另外要注意 where 1=1 的作用:保证有where,确保SQL语句正确
where标签
为了简化上面 where 1=1 的条件拼装,我们可以采用where标签来简化开发 。标签会将用到的第一个条件的and或or去掉
持久层Dao映射配置
<!-- 根据用户信息查询 -->
<select id="findByUser" resultType="user" parameterType="user">
select * from user
<where>
<if test="username!=null and username != '' ">
and username like #{username}
</if>
<if test="address != null">
and address like #{address}
</if>
</where>
</select>
foreach标签
传入多个 id 查询用户信息,用下边两个 sql 实现: SELECT * FROM USERS WHERE username LIKE ‘%张%’ AND (id =10 OR id =89 OR id=16) SELECT * FROM USERS WHERE username LIKE ‘%张%’ AND id IN (10,89,16) 这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。 这样我们将如何进行参数的传递?
第一种方式:
-
在 QueryVo 中加入一个 List 集合用于封装参数
/** * * <p>Title: QueryVo</p> * <p>Description: 查询的条件</p> * <p>Company: http://www.itheima.com/ </p> */ public class QueryVo implements Serializable { private List<Integer> ids; //生成set/get }
-
持久层 Dao 接口
/** * 根据 id 集合查询用户 * @param vo * @return */ List<User> findInIds(QueryVo vo);
-
持久层DAO映射配置
<!-- 查询所有用户在 id 的集合之中 --> <select id="findInIds" resultType="user" parameterType="queryvo"> select * from user <where> <if test="ids != null and ids.size() > 0"> <foreach collection="ids" open="id in ( " close=")" item="uid" separator=","> #{uid} </foreach> </if> </where> </select> 上面生成的SQL 语句是: select * from user where id in (XX,XX,XX); <foreach>标签用于遍历集合,它的属性: collection:代表要遍历的集合元素,注意编写时不要写#{} open:代表语句的开始部分 close:代表结束部分 item:代表遍历集合的每个元素,生成的变量名 sperator:代表分隔符
第二种方式:
-
持久层dao接口
/** * 根据 id 集合查询用户 * @param vo * @return */ //接收一个List参数 List<User> findInIds(List<String> ids); //或者用@Param注解标注,配置文件中的collection属性就要写注解的名称 //List<User> findInIds(@Param("userIds") List<String> ids);
-
持久层dao映射配置
<select id="findInIds" parameterType="String" resultType="user"> select * from user where id in <foreach collection="list" open="(" close=")" item="uid" separator=","> #{uid} </foreach> <!-- <foreach collection="userIds" open="(" close=")" item="uid" separator=","> #{uid} </foreach> --> </select> 如果参数是一个数组或者集合,collection属性要写相应的类型list,map,array 或者在形参上用@Param注解指定参数的名字,collection属性就要写指定的名字
SQL片段
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
-
定义代码片段
<!-- 抽取重复的语句代码片段 --> <sql id="defaultSql"> select * from user </sql>
-
引用代码片段
<!-- 配置查询所有操作 --> <select id="findAll" resultType="user"> <include refid="defaultSql"></include> </select> <!-- 根据 id 查询 --> <select id="findById" resultType="UsEr" parameterType="int"> <include refid="defaultSql"></include> where id = #{uid} </select>
Set标签
动态配置set关键字,并剔除追加到条件末尾任何不相关的逗号,使用if+set标签修改后,在进行表单更新操作中,当字段有值时才更新,如果为null,则不更新保持数据库原值
-
持久层dao接口
void updateUser(User user);
-
持久层dao映射配置
<update id="updateUser" parameterType="user"> update user <set> <if test="username != null and username!=''"> username=#{username}, </if> <if test="address!=null and address!=''"> address=#{address}, </if> </set> where id=1 </update>
trim标签
trim 是一个格式化标签,可以完成< set > 或者是 < where > 标记的功能主要有4个参数: ① prefix:在trim标签内sql语句加上前缀
② prefixOverrides:指定去除多余的前缀内容。如:prefixOverrides=”and | or” 指 去掉多余的and或者是or |
③ suffix:在trim标签内sql语句加上后缀
④ suffixOverrides:指定去除多余的后缀内容。如:suffixOverrides=“,” 指去掉最后一个逗号
-
替换where
<select id="findUserByCondition" parameterType="user" resultType="user"> select * from user <trim prefix="where" prefixOverrides="and | or"> <if test="username != null and username!=''"> and username=#{username} </if> </trim> </select> 如果username不为空,则生成的sql语句为: select * from user where username="XXX" username前面的and会自动去掉
-
替换update
<update id="updateUser" parameterType="user"> update user <trim prefix="set" suffixOverrides=","> <if test="username != null and username!=''"> username=#{username}, </if> <if test="address!=null and address!=''"> address=#{address}, </if> </trim> where id=#{id} </update> 如果username不为空,address为空,则生成的sql语句为: update user set username="XXX" where id="XXX" username后面的逗号会自动去掉
choose、when、otherwise 标签
这三个标签需要组合在一起使用,类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件。
-
持久层dao接口
List<User> findUser1(@Param("username") String username, @Param("address") String address, @Param("id") String id);
-
持久层dao映射配置
<select id="findUser1" resultType="user"> select * from user <where> <choose> <when test="username!=null and username!=''"> and username=#{username} </when> <when test="address!=null and address!=''"> and address=#{address} </when> <otherwise> and id=#{id} </otherwise> </choose> </where> </select> 此时即使username和address的值都不为空,那么sql也只会添加username的值
bind标签
bind标签可以使用OGNL表达式创建一个变量并将其绑定到上下文中。比如由于数据库不同,语法上会存在差异,更换数据库时部分sql语句需要修改,此时使用bind即可解决,也能防止SQL注入
<if test="username!=null and username!=''">
<!-- concat:mysql的连接字符串函数,不同的数据库不同-->
and username like concat('%',#{username},"%")
</if>
可以使用 bind标签改造
<if test="username!=null and username!=''">
<bind name="userNameLike" value="'%' + userName + '%'"/>
and username like #{userNameLike}
</if>