14 动态SQL

张创琦 2022.03.13

减少拼接SQL语句的麻烦之处。

1 where 标签在 select 中的作用

原来的动态SQL写法,十分麻烦,容易出错。

  1. /*原有的多条件分析:都是通过java中的字符串拼接实现String sql="select * from team where 1 = 1 ";
  2. // 如果用户输入了名称,就模糊查询
  3. and teamName like '%?%'
  4. // 如果用户输入了日期,按照日期区间查询
  5. and createTime> ? and createTime< ?
  6. //如果输入了地区,按照地区查询and location =?";*/
  7. if(vo.getName()!=null && !"".equals(vo.getName().trim())){
  8. sql+=" and teamName like '%"+vo.getName().trim()+"%'";
  9. }
  10. if(vo.getBeginTime()!=null ){
  11. sql+=" and getEndTime>"+vo.getBeginTime();
  12. }
  13. if(vo.getBeginTime()!=null ){
  14. sql+=" and createTime<="+vo.getEndTime();
  15. }
  16. if(vo.getLocation()!=null && !"".equals(vo.getLocation().trim())){
  17. sql+=" and location ="+vo.getLocation().trim();
  18. }

QueryTeamVO.java

  1. package com.kkb.pojo;
  2. import java.util.Date;
  3. /**
  4. * ClassName: QueryVO
  5. * 自己封装的球队查询条件
  6. * @author wanglina
  7. * @version 1.0
  8. */
  9. public class QueryTeamVO {
  10. private String name;
  11. private Date beginTime;
  12. private Date endTime;
  13. private String location;
  14. public String getName() {
  15. return name;
  16. }
  17. public void setName(String name) {
  18. this.name = name;
  19. }
  20. public Date getBeginTime() {
  21. return beginTime;
  22. }
  23. public void setBeginTime(Date beginTime) {
  24. this.beginTime = beginTime;
  25. }
  26. public Date getEndTime() {
  27. return endTime;
  28. }
  29. public void setEndTime(Date endTime) {
  30. this.endTime = endTime;
  31. }
  32. public String getLocation() {
  33. return location;
  34. }
  35. public void setLocation(String location) {
  36. this.location = location;
  37. }
  38. }

TeamMapper.java接口添加:

  1. List<Team> queryByVO(QueryTeamVO vo);

TeamMapper.xml映射文件添加:

  1. <!--多条件查询:
  2. 模糊查询的写法可以使用3种方式:
  3. 方式1: and teamName like #{name} ,传递参数的时候带上%,例如vo.setName("%人%")
  4. 方式2: and teamName like ‘%${name}%’ 传递参数的时候没有%,例如vo.setName("人")
  5. 方式3: and teamName like concat(concat('%',#{name}),'%') 例如vo.setName("人") concat(str1,str2)函数是字符串拼接使用-->
  6. <select id="queryByVO" parameterType="QueryVO" resultMap="baseResultMap">
  7. select * from team
  8. <where>
  9. <!-- 如果用户输入了名称,就模糊查询 and teamName like '%?%'-->
  10. <if test="name!=null ">
  11. and teamName like concat(concat('%',#{name}),'%')
  12. </if>
  13. <if test="beginTime!=null ">
  14. and createTime>=#{beginTime}
  15. </if>
  16. <if test="endTime!=null ">
  17. and createTime&lt;=#{endTime}
  18. </if>
  19. <if test="location!=null ">
  20. and location=#{location}
  21. </if>
  22. </where>
  23. </select>

TestSQL.java

  1. package com.kkb.test;
  2. import com.kkb.mapper.TeamMapper;
  3. import com.kkb.pojo.QueryTeamVO;
  4. import com.kkb.pojo.Team;
  5. import com.kkb.utils.MybatisUtil;
  6. import org.junit.Test;
  7. import java.util.Date; import java.util.List;
  8. /**
  9. * ClassName: TestSQL
  10. * 测试类
  11. * @author wanglina
  12. * @version 1.0
  13. */
  14. public class TestSQL {
  15. private TeamMapper teamMapper = MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
  16. @Test
  17. public void test1(){
  18. QueryTeamVO vo=new QueryTeamVO();
  19. vo.setName("人");// 依次添加查询条件添加控制台的SQL语句
  20. //vo.setEndTime(new Date());//依次添加查询条件观察控制台的SQL语句
  21. //vo.setLocation("加利福尼亚州洛杉矶");//依次添加查询条件观察控制台的SQL语句
  22. List<Team> teams = teamMapper.queryByVO(vo);
  23. for (Team team : teams) { System.out.println(team);
  24. }
  25. }
  26. }

运行结果:

  1. Preparing: select * from team WHERE teamName like concat(concat('%',?),'%')

2 set 标签在 update 中的作用

1 更新的原有写法

  1. TeamMapper.java接口中的方法:
  1. int update(Team team);
  1. TeamMapper.xml映射文件对应的内容:
  1. <update id="update" parameterType="com.kkb.pojo.Team">
  2. update team set teamName=#{teamName},location=#{location},createTime=#{createTime} where teamId=#{teamId}
  3. </update>
  1. 测试类中添加测试方法:
  1. TeamMapper teamMapper=MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
  2. @Test
  3. public void test2(){
  4. Team team=new Team();
  5. team.setTeamId(1055); team.setTeamName("lina");
  6. int update = teamMapper.update2(team);
  7. MybatisUtil.getSqlSession().commit();
  8. System.out.println(update);
  9. }

测试结果:

  1. DEBUG [main] - ==> Preparing: update team set teamName=?,location=?,createTime=? where teamId=?
  2. DEBUG [main] - ==> Parameters: lina(String), null, null, 1063(Integer)
  3. DEBUG [main] - <== Updates: 1
  4. DEBUG [main] - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@64cd705f]
  5. 1

弊端:没有赋值的属性会被赋值为空。

2 使用set标签构建动态的SQL语句

  1. TeamMapper.java接口中添加方法:
  1. int update1(Team team);
  1. TeamMapper.xml映射文件对应的内容:
  1. <update id="update1" parameterType="com.kkb.pojo.Team"> update team
  2. <set>
  3. <if test="teamName!=null"> teamName=#{teamName},</if>
  4. <if test="location!=null"> location=#{location},</if>
  5. <if test="createTime!=null"> createTime=#{createTime},</if>
  6. </set>
  7. where teamId=#{teamId}
  8. </update>
  1. 测试代码
  1. @Test
  2. public void test2(){
  3. Team team=new Team();
  4. team.setTeamId(1055);
  5. team.setTeamName("lina");
  6. int update = teamMapper.update1(team);
  7. MybatisUtil.getSqlSession().commit();
  8. System.out.println(update);
  9. }
  1. 测试结果
  1. DEBUG [main] - ==> Preparing: update team SET teamName=? where teamId=?
  2. DEBUG [main] - ==> Parameters: lina(String), 1055(Integer)
  3. DEBUG [main] - <== Updates: 0
  4. DEBUG [main] - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@20deea7f]
  5. 0

优点:动态SQL只更新非空属性列。

3 forEach 标签

1 批量添加

  1. TeamMapper.java接口中添加方法:
  1. void addList(List<Team> list);
  1. TeamMapper.xml映射文件对应的内容:
  1. <!--批量添加-->
  2. <insert id="addList" parameterType="arraylist"> INSERT INTO team (teamName,location) VALUES
  3. <!--collection:要遍历的集合;参数是集合类型,直接写list
  4. item:遍历的集合中的每一个数据separator:将遍历的结果用,分割-->
  5. <foreach collection="list" item="t" separator=","> (#{t.teamName},#{t.location})
  6. </foreach>
  7. </insert>
  1. 编写测试类
  1. @Test
  2. public void test3(){
  3. List<Team> list=new ArrayList<>();
  4. for(int i=1;i<=3;i++){
  5. Team team=new Team();
  6. team.setTeamName("lina"+i);
  7. team.setLocation("bj"+i);
  8. list.add(team);
  9. }
  10. teamMapper.addList(list);
  11. MybatisUtil.getSqlSession().commit();
  12. }
  1. 运行结果
  1. DEBUG [main] - ==> Preparing: INSERT INTO team (teamName,location) VALUES (?,?) , (?,?) , (?,?)
  2. DEBUG [main] - ==> Parameters: lina1(String), bj1(String), lina2(String), bj2(String), lina3(String), bj3(String)
  3. DEBUG [main] - <== Updates: 3
  4. DEBUG [main] - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3835c46]

2 批量删除

  1. TeamMapper.java接口中添加方法:
  1. void delList(List<Integer> list);
  1. TeamMapper.xml映射文件对应的内容:
  1. <!-- 批量删除 -->
  2. <delete id="delList" >
  3. delete from team where teamId in
  4. <!--collection:要遍历的集合;参数是集合类型,直接写list item:遍历的集合中的每一个数据
  5. separator:将遍历的结果用,分割
  6. open="(" close=")":表示将遍历结果用open close包裹起来-->
  7. <foreach collection="list" item="teamId" separator="," open="(" close=")">
  8. #{teamId}
  9. </foreach>
  10. </delete>
  1. 编写测试类
  1. @Test
  2. public void test4() {
  3. List<Integer> list = new ArrayList<>();
  4. list.add(1109);
  5. list.add(1110);
  6. list.add(1111);
  7. teamMapper.delList(list);
  8. MybatisUtil.getSqlSession().commit();
  9. }
  1. 代码结果
  1. DEBUG [main] - ==> Preparing: delete from team where teamId in ( ? , ? , ? )
  2. DEBUG [main] - ==> Parameters: 1109(Integer), 1110(Integer), 1111(Integer)
  3. DEBUG [main] - <== Updates: 0
  4. DEBUG [main] - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3835c46]