Mybatis之动态sql

动态sql

格式

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

实例

更新密码或者年龄

  • 首先在UserMapper.java中添加抽象方法
    • 因为要一个方法兼具更新密码或者更新年龄的功能,那么我们直接使用一个实体类对象作为方法参数即可
	/**
	 * 更新数据,比如密码或者年龄
	 * @param user  User对象,其中封装了用户密码或者用户的年龄
	 * @return 受影响的行数,成功返回1,否则返回0
	 */
	Integer update(User user);
  • UserMapper.xml中配置<update>节点
    • 只能修改密码或者年龄,不能同时修改,因为如果同时修改拼接而成的sql语句将会少了一个逗号,
 	<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的值
	@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中添加接口方法
	/**
	 * 查找用户信息,根据用户名或者用户id查询
	 * @param user  User对象,其中封装了用户名或者用户id
	 * @return 用户对象
	 */
	User findUser(User user);
  • UserMapper.xml中配置
<!-- 
		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>
  • 测试方法
@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搭配使用
<select>
	select * from user where
    <choose>
    	<when test="password!=null">
        	password=#{password}
        </when>
        
        <otherwise>
        	id=#{id}
        </otherwise>
    </choose>
</select>

where元素

问题

  • 我们使用动态sql语句构建的语句如下
<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去掉

格式

select 字段 from 表名
	<where>
		.....
	</where>

解决问题

  • 我们使用<where>标签解决上面的问题
<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构建一个更新语句,如下:
<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>元素,那么我们可以动态的修改字段

格式

update table_name 
	<set>
		......
	</set>

实例

  • 解决上面的问题
<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个映射就可以解决

总结

  1. 虽然在动态sql中,有很多标签可以实现对SQL语句的编程,但是,使用动态SQL的原则应该是希望代码复用,而不是编程,更不要用动态sql解决业务方法的问题

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Janti

Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition

锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock。 本文就不介绍synchronize了,有兴...

4276
来自专栏JavaEE

Java面试题 - 01

其实对于大多数刚入门的初级程序员来说,写代码都还停留在复制粘贴修改阶段(我也一样),虽然可以复制粘贴的时候看上去很厉害了,其实都是假象。面试的时候可能面试官随便...

1503
来自专栏皮振伟的专栏

[nptl][pthread]一种判断thread是否在执行的方法

前言: 主线程中怎么确定某线程是否在执行? 作者遇到这个问题,第一感觉有点蒙。翻了一下glibc的代码,算是找到一个比较好的办法吧。 分析: 1,变量控制 ...

3169
来自专栏烙馅饼喽的技术分享

用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- CustomYieldInstruction 自定义中断指令

ActionScript3脚本引擎为了方便热更新逻辑开发,提供的从脚本继承Unity类库功能在一些情况下可以提供开发的便利。 这次来建立一个示例,演示一下如何在...

3549
来自专栏好好学java的技术栈

java基础提升篇:深入浅出Java多线程

1272
来自专栏Java架构沉思录

你真的懂volatile关键字吗

volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结...

1171
来自专栏Java架构沉思录

一文理清Java内存区域

Java虚拟机在执行 Java 程序的过程中会把它管理的内存划分为若干个不同的数据区域。根据《Java 虚拟机规范》将 Java虚拟机所管理的内存分为以下几个运...

1092
来自专栏海天一树

小朋友学Java(12):包

包(package)是Java语言提供的一种区别类名字命名空间的机制,它是类的一种文件组织和管理方式、是一组功能相似或相关的类或接口的集合。Java packa...

2936
来自专栏TechBox

【iOS】运行时消息传递与转发机制前言(一)对象的消息传递机制 objc_msgSend()(二)消息转发流程参考文章

1284
来自专栏李家的小酒馆

Java面试基本知识

Java基本知识 基本知识 服务器:Tomcat 支持Servlet jsp JBoss 开源应用服务器 Apache:最广泛的http服务器,只支持静态网页 ...

2620

扫码关注云+社区

领取腾讯云代金券