【09】动态sql


通过mybatis提供的各种标签方法实现动态拼接sql。

1. if 、2. where

  • Mapper.xml

      <!-- sql 片段 -->
      <sql id="usercolumn">
      		id ,username , sex , birthday , address
      </sql>
      
      <select id="findUserList" parameterType="user" resultType="user">
      	select <include refid="usercolumn" /> from `user`
      	<where>
      		<if test="username!=null and username != ''">
      			and username like '%${username}%'
      		</if>
      		<if test="sex != null and sex != ''">
      			and sex = #{sex}
      		</if>
      		<if test="address != null and address != ''">
      			and address like '%${address}%'
      		</if>
      	</where>
      </select>
    

where 可以自动处理第一个and。

  • Mapper接口

       /**
    	 * 根据传入的user对象的属性,查询匹配的用户列表
    	 * @param user
    	 * @return
    	 */
    	public List<User> findUserList(User user);
    
  • 测试:

    	@Test
    	public void method01() throws IOException {
    
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		User user = new User();
    		user.setUsername("张");
    		user.setBirthday(new Date());
    		user.setSex("男");
    		user.setAddress("文化东路");
    		
    		UserMapper userDao = sqlSession.getMapper(UserMapper.class);
    		List<User> userlist = userDao.findUserList(user);
    		System.out.println(userlist);
    		sqlSession.close();
    	}
    

3. set、if

  • Mapper.xml

    	<update id="updateUser2" parameterType="user">
    		UPDATE `USER`
    		<set>
    			<if test="username != null">username = #{username} ,</if>
    			<if test="birthday != null">birthday = #{birthday} ,</if>
    			<if test="sex != null">sex = #{sex} ,</if>
    			<if test="address != null">address = #{address} ,</if>
    		</set>
    		WHERE ID = #{id}
    	</update>
    
  • Mapper接口

      /**
      	 * 更新用户
      	 * @param user
      	 */
      	public int updateUser2(User user);
    
  • 测试:

    	@Test
    	public void method02() throws IOException {
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		
    		User user = new User();
    		user.setId(14);
    		user.setUsername("张小三");
    		
    		user.setBirthday(java.sql.Date.valueOf("1995-6-9"));
    		user.setSex("男");
    		user.setAddress("文化东路55");
    		
    		UserMapper userDao = sqlSession.getMapper(UserMapper.class);
    		int i = userDao.updateUser2(user);
    		System.out.println(i);
    		
    		sqlSession.commit();//提交事务
    		sqlSession.close();
    	}
    

4. foreach

向sql传递数组或List,mybatis使用foreach解析,如下:

4.1 通过pojo传递list

  • 需求
    传入多个id查询用户信息,用下边两个sql实现:

      SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
      SELECT * FROM USERS WHERE username LIKE '%张%'  id IN (10,89,16)
    
  • 在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法
    在这里插入图片描述

  • mapper.xml

        <if test="ids!=null and ids.size>0">
        	<foreach collection="ids" open=" and id in(" close=")" item="id" separator="," >
        	   		#{id}
        	</foreach>
        </if>
    
  • 测试代码:

    	List<Integer> ids = new ArrayList<Integer>();
    	ids.add(1);//查询id为1的用户
    	ids.add(10); //查询id为10的用户
    	queryVo.setIds(ids);
    	List<User> list = userMapper.findUserList(queryVo);
    

4.2 传递单个List

传递List类型在编写mapper.xml没有区别,唯一不同的是只有一个List参数时它的参数名为list。

  • Mapper.xml

        <select id="selectUserByList" parameterType="java.util.List" resultType="user">
      		select * from user 
      		<where>
      		<!-- 传递List,List中是pojo -->
      		<if test="list!=null and list.size() >0 ">
      		<foreach collection="list" item="item" open="and id in("separator=","close=")">
      		    #{item.id} 
      		</foreach>
      		</if>
      		</where>
      	</select>
    
  • Mapper接口

        public List<User> selectUserByList(List userlist) throws Exception;
    
  • 测试:

        public void testselectUserByList()throws Exception{
      		//获取session
      		SqlSession session = sqlSessionFactory.openSession();
      		//获限mapper接口实例
      		UserMapper userMapper = session.getMapper(UserMapper.class);
      		//构造查询条件List
      		List<User> userlist = new ArrayList<User>();
      		User user = new User();
      		user.setId(1);
      		userlist.add(user);
      		user = new User();
      		user.setId(2);
      		userlist.add(user); 
      		//传递userlist列表查询用户列表
      		List<User>list = userMapper.selectUserByList(userlist);
      		//关闭session
      		session.close();
      	}
    

4.3 传递单个数组(数组中是pojo):

  • Mapper.xml

      	<!-- 传递数组综合查询用户信息 -->
      	<select id="selectUserByArray" parameterType="Object[]" resultType="user">
      		select * from user 
      		<where>
      		<!-- 传递数组 -->
      		<if test="array!=null and array.length != 0">
      		<foreach collection="array" index="index" item="item" open="and id in("separator=","close=")">
      		    #{item.id} 
      		</foreach>
      		</if>
      		</where>
      	</select>
    

sql只接收一个数组参数,这时sql解析参数的名称mybatis固定为array,如果数组是通过一个pojo传递到sql则参数的名称为pojo中的属性名。
index:为数组的下标。
item:为数组每个元素的名称,名称随意定义
open:循环开始
close:循环结束
separator:中间分隔输出

  • Mapper接口:

        public List<User> selectUserByArray(Object[] userlist) throws Exception;
    
  • 测试:

       public void testselectUserByArray()throws Exception{
      	  //获取session
      	  SqlSession session = sqlSessionFactory.openSession();
      	  //获限mapper接口实例
      	  UserMapper userMapper = session.getMapper(UserMapper.class);
      	  //构造查询条件List
      	  Object[] userlist = new Object[2];
      	  User user = new User();
      	  user.setId(1);
      	  userlist[0]=user;
      	  user = new User();
      	  user.setId(2);
      	  userlist[1]=user;
      	  //传递user对象查询用户列表
      	  List<User>list = userMapper.selectUserByArray(userlist);
      	  //关闭session
      	  session.close();
      }
    

4.4 传递单个数组(数组中是字符串类型):

  • Mapper.xml

      <!-- 传递数组综合查询用户信息 -->
      <select id="selectUserByArray" parameterType="Object[]" resultType="user">
      	select * from user 
      	<where>
      		<!-- 传递数组 -->
      		<if test="array!=null">
      			<foreach collection="array"index="index"item="item"open="and id in("separator=","close=")">
      	    		#{item} 
      			</foreach>
      		</if>
      	</where>
      </select>
    

如果数组中是简单类型则写为#{item},不用再通过ognl获取对象属性值了。

  • Mapper接口:

      public List<User> selectUserByArray(Object[] userlist) throws Exception;
    
  • 测试:

      public void testselectUserByArray()throws Exception{
      	//获取session
      	SqlSession session = sqlSessionFactory.openSession();
      	//获限mapper接口实例
      	UserMapper userMapper = session.getMapper(UserMapper.class);
      	//构造查询条件List
      	Object[] userlist = new Object[2];
      	userlist[0]=”1”;
      	userlist[1]=”2”;
      	//传递user对象查询用户列表
      	List<User>list = userMapper.selectUserByArray(userlist);
      	//关闭session
      	session.close();
      }
    

5. choose、when、otherwise

  • 不想选择所有的查询条件,指向选择其中的一个,查询条件有一个满足即可,可以使用choose标签。
  • Mapper.xml
	<select id="findUserList2" parameterType="user"
		resultType="user">
		select
		<include refid="usercolumn" />
		from `user`
		<where>
			<choose>
				<when test="username!=null and username != ''">
					and username like '%${username}%'
				</when>
				<when test="sex != null and sex != ''">
					and sex = #{sex}
				</when>
				<when test="address != null and address != ''">
					and address like '%${address}%'
				</when>
				<otherwise>
					and 1 = 2
				</otherwise>
			</choose>
		</where>
	</select>

6. trim语句

  • trim标记是一个格式化标记,可以完成set或者where标记的功能

  • trim改写if+where

      <select id="findUserList" parameterType="user" resultType="user">
      		select <include refid="usercolumn" /> from `user`
      		<trim prefix = "where" prefixOverrides= "and | or" >
      			<if test="username!=null and username != ''">
      				and username like '%${username}%'
      			</if>
      			<if test="sex != null and sex != ''">
      				and sex = #{sex}
      			</if>
      			<if test="address != null and address != ''">
      				and address like '%${address}%'
      			</if>
      		</trim>
      </select>
    

prifix:前缀
prefixOverrides : 去掉第一个 and 或者是 or

  • trim改写if+where

      <update id="updateUser2" parameterType="user">
      	UPDATE `USER`
      	<trim prefix = "set" prefixOverrides= "," >
      		<if test="username != null">username = #{username} ,</if>
      		<if test="birthday != null">birthday = #{birthday} ,</if>
      		<if test="sex != null">sex = #{sex} ,</if>
      		<if test="address != null">address = #{address} ,</if>
      	</trim >
      	WHERE ID = #{id}
      </update>
    

prifix:前缀
prefixOverrides : 去掉第一个 and 或者是 or

7. Sql片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,如下:

	<!-- 传递pojo综合查询用户信息 -->
	<select id="findUserList" parameterType="user" resultType="user">
		select * from user 
		<where>
			<if test="id!=null and id!=''">
				and id=#{id}
			</if>
			<if test="username!=null and username!=''">
				and username like '%${username}%'
			</if>
		</where>
	</select>

 将where条件抽取出来:

	<sql id="query_user_where">
		<if test="id!=null and id!=''">
			and id=#{id}
		</if>
		<if test="username!=null and username!=''">
			and username like '%${username}%'
		</if>
	</sql>

 使用include引用:

	<select id="findUserList" parameterType="user" resultType="user">
		select * from user 
		<where>
			<include refid="query_user_where"/>
		</where>
	</select>

注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:
<include refid="namespace.sql片段”/>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值