前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MyBatis之动态sql

MyBatis之动态sql

作者头像
爱撒谎的男孩
发布2019-12-31 15:01:30
6260
发布2019-12-31 15:01:30
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

文章目录

  1. 1. 动态sql
    1. 1.1. if子句
      1. 1.1.1. 格式
      2. 1.1.2. 实例
        1. 1.1.2.1. 更新密码或者年龄
        2. 1.1.2.2. 根据用户名或者用户id查询信息
    2. 1.2. choose【了解】
    3. 1.3. where元素
      1. 1.3.1. 问题
      2. 1.3.2. 作用
      3. 1.3.3. 格式
      4. 1.3.4. 解决问题
    4. 1.4. set元素
      1. 1.4.1. 问题
      2. 1.4.2. 解决
      3. 1.4.3. 格式
      4. 1.4.4. 实例
    5. 1.5. where 元素
    6. 1.6. 作用
    7. 1.7. forEach
      1. 1.7.1. 持久层
        1. 1.7.1.1. 接口中定义方法
        2. 1.7.1.2. 配置文件中配置
    8. 1.8. 总结

动态sql

if子句

格式

  • <if test="">
    • test中填写的是判断条件

实例

更新密码或者年龄
  • 首先在UserMapper.java中添加抽象方法
    • 因为要一个方法兼具更新密码或者更新年龄的功能,那么我们直接使用一个实体类对象作为方法参数即可
代码语言:javascript
复制
/**
 * 更新数据,比如密码或者年龄
 * @param user  User对象,其中封装了用户密码或者用户的年龄
 * @return 受影响的行数,成功返回1,否则返回0
 */
Integer update(User user);
  • UserMapper.xml中配置<update>节点
    • 只能修改密码或者年龄,不能同时修改,因为如果同时修改拼接而成的sql语句将会少了一个逗号,
代码语言:javascript
复制
<update id="update" parameterType="cn.tedu.spring.entity.User">
	update user 
	set
	<if test="password!=null">
		password=#{password}
	</if>
	<if test="age!=null">
		age=#{age}
	</if>
	where id=#{id}
</update>
  • 测试
    • 修改年龄age,因此只需要在新建的User对象中添加age的值即可,那么此时password的值不能设置
    • 同时要设置id的值
代码语言:javascript
复制
@Test
public void testUpdate() {
	//加载Spring的配置文件
	AbstractApplicationContext ac
		= new ClassPathXmlApplicationContext(
			"spring-mvc.xml",
			"spring-dao.xml");
	
	//获取UserMapper的bean,这个是spring通过扫描mapper.xml文件自动为mybatis自动创建的,首字母小写
	UserMapper userMapper
		= ac.getBean(
			"userMapper", UserMapper.class);
	//新建一个User对象
	User user=new User();
	user.setId(3);  //设置id
	user.setAge(33);  //设置年龄
	int affectRows=userMapper.update(user);
	System.out.println(affectRows);
	ac.close();
}
根据用户名或者用户id查询信息
  • UserMpper.java中添加接口方法
代码语言:javascript
复制
/**
 * 查找用户信息,根据用户名或者用户id查询
 * @param user  User对象,其中封装了用户名或者用户id
 * @return 用户对象
 */
User findUser(User user);
  • UserMapper.xml中配置
代码语言:javascript
复制
<!-- 
		User findUser(User user); 
		不能同时查询,缺少连接符号 and or
	-->
	<select id="findUser" parameterType="cn.tedu.spring.entity.User" resultType="cn.tedu.spring.entity.User">
		select * from user 
		where 
		<if test="id!=null">
			id=#{id}
		</if>
		
		<if test="username!=null">
			username=#{username}
		</if>
		
	</select>
  • 测试方法
代码语言:javascript
复制
@Test
	public void testFind() {
		//加载Spring的配置文件
		AbstractApplicationContext ac
			= new ClassPathXmlApplicationContext(
				"spring-mvc.xml",
				"spring-dao.xml");
		
		//获取UserMapper的bean,这个是spring通过扫描mapper.xml文件自动为mybatis自动创建的,首字母小写
		UserMapper userMapper
			= ac.getBean(
				"userMapper", UserMapper.class);
		//新建一个User对象
		User user=new User();
		user.setId(3);  //设置id
		//根据id查找
		System.out.println(userMapper.findUser(user));
		ac.close();
	}

choose【了解】

  • 相当于java中的switch,通常与when搭配使用
代码语言:javascript
复制
<select>
	select * from user where
    <choose>
    	<when test="password!=null">
        	password=#{password}
        </when>
        
        <otherwise>
        	id=#{id}
        </otherwise>
    </choose>
</select>

where元素

问题

  • 我们使用动态sql语句构建的语句如下
代码语言:javascript
复制
<select id="findUser" parameterType="cn.tedu.spring.entity.User" resultType="cn.tedu.spring.entity.User" >
	select * from user 
    where 
    <if test="password!=null">
    	password=#{password}
    </if>
    
    <if test="username!=null">
    	and username=#{username}
    </if>
    
</select>
  • 如果传入的参数User对象中只是设置了username的值,那么此时的sql语句将会变成select * from user where and username=#{username},很明显多了一个and

作用

  • <where>标签主要是用于简化where子句的编写,<where>可以替代sql语句中的where,而且还可以将后面多余的and或者or去掉

格式

代码语言:javascript
复制
select 字段 from 表名
	<where>
		.....
	</where>

解决问题

  • 我们使用<where>标签解决上面的问题
代码语言:javascript
复制
<select id="findUser" parameterType="cn.tedu.spring.entity.User" resultType="cn.tedu.spring.entity.User" >
	select * from user 
    <where>
        <if test="password!=null">
           and password=#{password}
        </if>

        <if test="username!=null">
            and username=#{username}
        </if>
    </where>
    
</select>
  • 如果此时在User对象中只是设置了一个username的值,那么会去掉前面的and关键字,并且此时的sql语句会变成:select * from user where username=#{username}

set元素

问题

  • 我们使用动态sql构建一个更新语句,如下:
代码语言:javascript
复制
<update id="update" parameterType="cn.tedu.spring.entity.User">
	 	update user 
	 	set
	 	<if test="password!=null">
	 		password=#{password},
	 	</if>
	 	
	 	<if test="age!=null">
	 		age=#{age},
	 	</if>
	 	
	 	<if test="username!=null">
	 		username=#{username}
	 	</if>
	 	
	 	where id=#{id}
	 </update>
  • 从上面的<update>中可以看出,如果我们在User对象中没有设置password,age,username的值,那么构建出来的sql语句变成了update user set where id=#{id},很明显是一个错误的语句。
  • 如果在User对象中值设置了password的值,那么这里的sql语句变成了update user set password=#{password}, where id=#{id},很明显,这个sql多了一个逗号

解决

  • 我们可以使用<set>,可以在<set>元素所在位置输出一个set关键字,而且可以去除内容结尾中无关的逗号,有了<set>元素,那么我们可以动态的修改字段

格式

代码语言:javascript
复制
update table_name 
	<set>
		......
	</set>

实例

  • 解决上面的问题
代码语言:javascript
复制
<update id="update" parameterType="cn.tedu.spring.entity.User">
	 	update user 
	 	<set>
            <if test="password!=null">
                password=#{password},
            </if>

            <if test="age!=null">
                age=#{age},
            </if>

            <if test="username!=null">
                username=#{username}
            </if>
	 	</set>
	 	where id=#{id}
	 </update>

where 元素

作用

  • 使用动态sql可以解决SQL语句中代码复用问题,即2处或者多处高度相似的代码,在使用动态SQL之后,1个方法和1个映射就可以解决

forEach

持久层

  • 根据传入的id批量删除商品,用sql语句如下:delete from t_cart where id in (1,2,3,4,4),因此参数应该是一个数组
接口中定义方法
  • 数组必须使用@Param()来指定
代码语言:javascript
复制
/**

	 * 根据id删除购物车中的商品

	 * @param ids

	 */

	void deleteCartById(@Param("ids")Integer[] ids);
配置文件中配置
  • 使用遍历数组中的元素
代码语言:javascript
复制
<!-- 
     	 	void deleteCartById(@Param("ids")Integer[] ids);
     	 	批量删除
     	  -->
     	  <delete id="deleteCartById" parameterType="java.lang.Integer">
     	  		delete from t_cart 
     	  		where
     	  		id in
     	  		<!-- 
     	  			遍历数组ids
     	  			collection:需要遍历的数组
     	  			item: 数组中的每一个值
     	  			open : 开始的内容
     	  			close: 结束的内容
     	  			separator :每个元素的分割符
     	  			最后拼接的就是  (id,id,id,id,id)
     	  		 -->
     	  		<foreach collection="ids" item="id" open="(" separator="," close=")">
     	  			#{id}
     	  		</foreach> 
     	  </delete>

总结

  1. 虽然在动态sql中,有很多标签可以实现对SQL语句的编程,但是,使用动态SQL的原则应该是希望代码复用,而不是编程,更不要用动态sql解决业务方法的问题
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态sql
    • if子句
      • 格式
      • 实例
    • choose【了解】
      • where元素
        • 问题
        • 作用
        • 格式
        • 解决问题
      • set元素
        • 问题
        • 解决
        • 格式
        • 实例
      • where 元素
        • 作用
          • forEach
            • 持久层
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档