9使用动态SQL

1、if

可以对传入的数据进行判断筛选。
测试类:

    @Test
	public void test01() {
		Map<String, Object> map = new HashMap<>();
		map.put("pname",null);
		map.put("page", 20);
		for(Student student : dao.selectStudentByIf(map)) {
			System.out.println(student);
		}
	}

之前的多条件查询sql:
是对名字的模糊查询并且年龄小于某个数字。

<select id="selectStudentByIf" resultType="Student">
	select id,name,age from student
	where name like '%' #{pname} '%' and age &lt; #{page}
</select>

可以看出sql语句是固定的,当其中两项条件中有某一项为null或者不存在时,查询结果就会出错。
在这里插入图片描述
这个时候在写sql语句的时候使用if标签,就可以避免缺少条件所导致的错误了。
使用if标签后的sql语句:
可以使用if添加判断条件,当参数不满足条件时,就不执行那一段sql。

<select id="selectStudentByIf" resultType="Student">
		select id,name,age from student
		where 
		<if test="pname != null and pname != ''">
			name like '%' #{pname} '%'
		</if> 
		<if test="page > 0">
			and age &lt; #{page}
		</if>
	</select>

这时就有个新的问题,当一个if不满足,满足第二个if时,拼接的sql就会是这个样子:
在这里插入图片描述
同样会导致查询失败。
可以在where语句后面添加一个不会影响sql运行的条件,并在两个if中的sql语句中都加上and。

<select id="selectStudentByIf" resultType="Student">
		select id,name,age from student
		where 1=1
		<if test="pname != null and pname != ''">
			and name like '%' #{pname} '%'
		</if> 
		<if test="page > 0">
			and age &lt; #{page}
		</if>
	</select>

这样就可以保证,不管满足哪一个条件都可以完成查询。
实际上使用where标签就可以很轻松的解决这个问题。

2、where

测试类:

@Test
	public void test02() {
		Map<String, Object> map = new HashMap<>();
		map.put("pname", null);
		map.put("page", 20);
		for(Student student : dao.selectStudentByWhere(map)) {
			System.out.println(student);
		}
	}

映射文件:

<select id="selectStudentByWhere" resultType="Student">
		select id,name,age from student
		<where>
			<if test="pname != null and pname != ''">
				and name like '%' #{pname} '%'
			</if>
			<if test="page > 0">
				and age &lt; #{page}
			</if>
		</where>
	</select>

使用了where标签之后,在if条件中的sql最好都加上and,这样即使只满足一个条件,也会自动省略and,不会出现sql拼接错误的情况。

3、choose

<select id="selectStudentByChoose" resultType="Student">
		select id,name,age from student
		<where>
			<choose>
				<when test="pname != null and pname != ''">
					and name like '%' #{pname} '%'
				</when>
				<when test="page > 0">
					and age &gt; #{page}
				</when>
				<otherwise>
					1 != 1
				</otherwise>
			</choose>
		</where>
	</select>

choose-when-otherwise表示多分支判断,类似于Java中的switch-case语句。

4、foreach

当要查询多条数据时使用。
使用foreach遍历数组:
测试类:

@Test
	public void test04() {
		Integer [] stu = {7,12,15};
		for(Student student : dao.selectStudentByForeach(stu)) {
			System.out.println(student);
		}
	}

查询出id为数组中定义的值的Student。
映射文件:

<select id="selectStudentByForeach" resultType="Student">
		select id,name,age from student
		<if test="array != null and array.length != 0">
			<where>
				id in
				<foreach collection="array" open="(" close=")" separator=","
					item="student">
					#{student}
				</foreach>
			</where>
		</if>
	</select>

注意:此时传入的是数组,所以在foreach中collection属性值要写成array。
实际上foreach就是把传入过来的数组数据拼接成( , , , )这个形式。
item的值可以任意设置,最后foreach中#{}里要填写item设置的值。
使用foreach遍历List集合:
测试类:

@Test
	public void test05() {
		List<Integer> stu2 = new ArrayList();
		stu2.add(7);
		stu2.add(17);
		stu2.add(18);
		for(Student student : dao.selectStudentByForeach2(stu2)) {
			System.out.println(student);
		}
	}

***映射文件:***`

<select id="selectStudentByForeach2" resultType="Student">
		select id,name,age from student
		<if test="list != null and list.size != 0">
			<where>
				id in
				<foreach collection="list" open="(" close=")" separator=","
					item="student">
					#{student}
				</foreach>
			</where>
		</if>
	</select>

collection属性要填写为list。
使用foreach遍历对象:
测试类:

@Test
	public void test06() {
		List<Student> stu2 = new ArrayList();
		Student student = new Student();
		student.setId(2);
		Student student2 = new Student();
		student2.setId(17);
		Student student3 = new Student();
		student3.setId(18);
		stu2.add(student);
		stu2.add(student2);
		stu2.add(student3);
		for(Student students : dao.selectStudentByForeach3(stu2)) {
			System.out.println(students);
		}
	}

映射文件:

<select id="selectStudentByForeach3" resultType="Student">
		select id,name,age from student
		<if test="list != null and list.size != 0">
			<where>
				id in
				<foreach collection="list" open="(" close=")" separator=","
					item="mystu">
					#{mystu.id}
				</foreach>
			</where>
		</if>
	</select>

因为最后遍历出来的是对象,所以使用 对象.id 的方式获取到id。

5、sql

在实际开发中往往定义的实体类会比较多,如果要进行全部查询的话,在sql语句的编写上就有点困难,还容易出错,但是使用select * 又会增加查询时间,所以这时就可以用用sql片段,将出现机会较多、容易出错的sql语句单独的进行编写,什么地方需要用到,就直接对对其引用。
测试类:

@Test
	public void test07() {//使用SQL片段的测试
		List<Student> stu2 = new ArrayList();
		Student student = new Student();
		student.setId(2);
		Student student2 = new Student();
		student2.setId(17);
		Student student3 = new Student();
		student3.setId(18);
		stu2.add(student);
		stu2.add(student2);
		stu2.add(student3);
		for(Student students : dao.selectStudentBySQLFragment(stu2)) {
			System.out.println(students);
		}
	}

测试的代码还是之前的代码,只不过调用的接口不同。
映射文件:

<!-- SQL片段的定义 -->
	<!-- SQL片段可以定义SQL语句中任一片段 -->
	<sql id="SQLFragment">
		id,name,age
	</sql>
	<!-- SQL片段的使用 -->
	<select id="selectStudentBySQLFragment" resultType="Student">
		select <include refid="SQLFragment"/> from student
		<if test="list != null and list.size != 0">
			<where>
				id in
				<foreach collection="list" open="(" close=")" separator=","
					item="mystu">
					#{mystu.id}
				</foreach>
			</where>
		</if>
	</select>

在sql标签中可以定义sql语句中任一连续的片段。再使用include标签在sql语句中进行拼接。
这样做的优点就是降低代码冗余、增加可维护性、降低编写错误的发生。
缺点就是使sql语句的可读性变差。
最后总体的接口:

public interface IStudentDao {

	List<Student> selectStudentByIf(Map<String, Object> map);//<if></if>
	List<Student> selectStudentByWhere(Map<String, Object> map);//<where></where>
	List<Student> selectStudentByChoose(Map<String, Object> map);//<choose></choose>
	List<Student> selectStudentByForeach(Integer [] stu);//<foreach></foreach>
	List<Student> selectStudentByForeach2(List<Integer> stu);
	List<Student> selectStudentByForeach3(List<Student> stu);
	List<Student> selectStudentBySQLFragment(List<Student> stu);//<sql></sql>
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚定你坚定的步伐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值