Mybatis基础(六)动态 SQL

本文深入介绍了MyBatis动态SQL的使用,包括if、where、foreach等标签的详细解析,并通过实例展示了如何在实际编程中应用这些标签。动态SQL简化了根据条件拼接SQL的过程,极大地提高了代码的可读性和维护性。文中还提到了SQL片段的使用,使得复杂SQL的编写更加便捷。
摘要由CSDN通过智能技术生成

一、动态 SQL简单介绍

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

二、标签简单介绍

1.if

<select id="findif" parameterType="entity.Student" resultType="entity.Student">
	select sn,sname from student1 where 1=1
	<if test="sname!=null">
		and sname like '%${sname}%'
		</if>		
</select>

上面使用了if标签,只有test里面是真值时,才会拼接and sname like ‘%${sname}%’ 这个语句。

2.choose (when, otherwise)

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<select id="findActive"
     resultType="entity.Student">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

3.trim (where, set)

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。

4.foreach

SQL映射文件通过parameterType来指定输入参数类型,如果输入参数是简单类型或一般对象类型,可以直接指定。但是如果输入参数是集合或者数组类型,就需要标签来完成输入输出参数的处理。

<!-- 将集合或数组以对象的形式传入 -->
<select id="findForeach" parameterType="entity.Grade" resultType="entity.Student">
	select * from student1
	<where>
		<if test="sns!=null">
			<!-- 使用foreach标签,迭代取出Grade对象中sn集合属性的每个元素 -->
			<foreach collection="sns" open="sn in("  close=")" item="sns"  separator=",">
				#{sns}
			</foreach>
		</if>
	</where>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

三、编写程序来实现if、where、foreach标签

数据库表及实体类:
在这里插入图片描述

package entity;

public class Student {
	private int sn;
	private String sname;
	private boolean ssex;
	private Address address;
	
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
	public int getSn() {
		return sn;
	}
	public void setSn(int sn) {
		this.sn = sn;
	}
	public String getsname() {
		return sname;
	}
	public void setsname(String sname) {
		this.sname = sname;
	}
	public boolean getSsex() {
		return ssex;
	}
	public void setSsex(boolean ssex) {
		this.ssex = ssex;
	}
	@Override
	public String toString() {
		return this.sname+"\t";
		}
}

1.实现if标签

定义配置文件mapper.xml

<select id="findif" parameterType="entity.Student" resultType="entity.Student">
	select sn,sname from student1 where 1=1
	<if test="sname!=null">
		and sname like '%${sname}%'
		</if>		
</select>

定义接口

List<Student> findif(Student sn);

编写测试方法

//实现if标签
	public static void testif() throws IOException{
		String resource="conf.xml";
		Reader reader=Resources.getResourceAsReader(resource);
		SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=sessionFactory.openSession();
		StudentDao st=session.getMapper(StudentDao.class);
		 Student stu=new Student();
		 stu.setsname("美");
		 List<Student> students=st.findif(stu);
		 System.out.println(students);
	}

运行测试方法:
在这里插入图片描述

2.实现where标签

定义配置文件mapper.xml

<select id="findif" parameterType="entity.Student" resultType="entity.Student">
	select sn,sname from student1 
	<where>
	<if test="sname!=null">
		and sname like '%${sname}%'
		</if>	
			</where>	
</select>

其他的和if标签是一样的
这里就省略运行了

3.实现foreach标签

定义新的实体类Grade

package entity;

import java.util.List;

public class Grade {
	private List<Integer> sns;

	public List<Integer> getSns() {
		return sns;
	}

	public void setSns(List<Integer> sns) {
		this.sns = sns;
	}
	
}

定义配置文件mapper.xml

<!-- 将集合或数组以对象的形式传入 -->
<select id="findForeach" parameterType="entity.Grade" resultType="entity.Student">
	select * from student1
	<where>
		<if test="sns!=null">
			<!-- 使用foreach标签,迭代取出Grade对象中sn集合属性的每个元素 -->
			<foreach collection="sns" open="sn in("  close=")" item="sns"  separator=",">
				#{sns}
			</foreach>
		</if>
	</where>
</select>

<!-- 传入List类型集合 -->

<select id="findForeach1" parameterType="java.util.List" resultType="entity.Student">
	select * from student1
	<where>
		<if test="list!=null and list.size>0">
			<!-- 使用foreach标签,迭代取出Grade对象中sn集合属性的每个元素 -->
			<foreach collection="list" open="sn in("  close=")" item="sns"  separator=",">
				#{sns}
			</foreach>
		</if>
	</where>
</select>

<!-- 传入简单类型的数组和SQL片段 -->
<select id="findForeach2" parameterType="int[]" resultType="entity.Student">
	select * from student1
	<where>
		<!-- 导入sql片段 -->
		<include refid="sql1"/>
		<!-- refid属性指向需要导入<sql>标签的id值-->
		<!-- 如果<include>的是其他映射文件的SQL片段,则需要加上namespace,比如<include refid="namespace.id"-->
	</where>
</select>

<!-- SQL片段 -->
<sql id="sql1">
<if test="array!=null and array.length>0">
			<!-- 使用foreach标签,迭代取出Grade对象中sn集合属性的每个元素 -->
			<foreach collection="array" open="sn in("  close=")" item="sns"  separator=",">
				#{sns}
			</foreach>
		</if>
</sql>

定义接口

	package dao;

import java.util.HashMap;
import java.util.List;

import entity.Grade;
import entity.Student;

public interface StudentDao {
	List<Student> findForeach(Grade grade);
	List<Student> findForeach1(List<Integer> sns);
	List<Student> findForeach2(int array[]);
}

编写测试方法

//实现foreach标签,将集合或数组的对象形式传入
	public static void testforeach()throws IOException{
		String resource="conf.xml";
		Reader reader=Resources.getResourceAsReader(resource);
		SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=sessionFactory.openSession();
		StudentDao st=session.getMapper(StudentDao.class);
		List<Integer> sns=new ArrayList<Integer>();
		
		sns.add(101);
		sns.add(102);
		sns.add(103);
		
		Grade grade=new Grade();
		
		grade.setSns(sns);
		//传入grade对象,该对象包含了List集合类型的属性sns;
		
		List<Student> students=st.findForeach(grade);
		 System.out.println(students);
	}
	
	//实现foreach标签, 传入List的集合
	public static void testforeachlist()throws IOException{
		String resource="conf.xml";
		Reader reader=Resources.getResourceAsReader(resource);
		SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=sessionFactory.openSession();
		StudentDao st=session.getMapper(StudentDao.class);
		List<Integer> sns=new ArrayList<Integer>();
		
		sns.add(99);
		sns.add(102);
		sns.add(103);
		
		List<Student> students=st.findForeach1(sns);
		 System.out.println(students);
	}
	//实现foreach标签, 传入简单类型的数组
	public static void testforeacharray()throws IOException{
		int[] array=new int[10];
		 array[0]=98;
		 array[1]=99;
		 String resource="conf.xml";
		Reader reader=Resources.getResourceAsReader(resource);
		SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);
		SqlSession session=sessionFactory.openSession();
		StudentDao st=session.getMapper(StudentDao.class);		
		 List<Student> students=st.findForeach2(array);
		 System.out.println(students);
	}
	

运行测试方法
在这里插入图片描述

四、简单介绍一下SQL片段

<!-- 传入简单类型的数组和SQL片段 -->
<select id="findForeach2" parameterType="int[]" resultType="entity.Student">
	select * from student1
	<where>
		<!-- 导入sql片段 -->
		<include refid="sql1"/>
		<!-- refid属性指向需要导入<sql>标签的id值-->
		<!-- 如果<include>的是其他映射文件的SQL片段,则需要加上namespace,比如<include refid="namespace.id"-->
	</where>
</select>

<!-- SQL片段 -->
<sql id="sql1">
<if test="array!=null and array.length>0">
			<!-- 使用foreach标签,迭代取出Grade对象中sn集合属性的每个元素 -->
			<foreach collection="array" open="sn in("  close=")" item="sns"  separator=",">
				#{sns}
			</foreach>
		</if>
</sql>

上面注解讲的很清楚了,使用的话在写一些复杂的程序就会更方便,可修改性也更好!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值