MyBatis学习笔记(六)动态sql

在一些情况下,如查询参数不确定时,需要用到动态sql

例子,根据动态输入的查询条件查询student.

一.if语句

1.StudentTMapper

package com.skymr.mybatis.mappers;

import java.util.List;
import java.util.Map;

import com.skymr.mybatis.model.Student;

public interface StudentTMapper {

	public List<Student> searchStudents(Map<String,Object> map);
}

map参数是查询条件

2.StudentTMappler.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:Mapper映射 -->
<!-- 这个文件感觉就像StudentMapper接口的实现一样,只是从java文件变成了xml文件
充当了Dao类的功能
 -->
<mapper namespace="com.skymr.mybatis.mappers.StudentTMapper">

	<resultMap type="Student" id="stuMap">
		<id property="id" column="id"/>
		<result property="name" column="name"/>
		<result property="age" column="age"/>
		<association property="address" column="address_id" select="com.skymr.mybatis.mappers.AddressMapper.getAddress">
		</association>
		<association property="grade" column="grade_id" select="com.skymr.mybatis.mappers.GradeMapper.getGrade"></association>
	</resultMap>
	<select id="searchStudents" resultMap="stuMap" parameterType="map">
		select * from mybatis_student where 1=1
		<if test="name!=null">
			and name like #{name}
		</if>
		<if test="age!=null">
			and age=#{age}
		</if>
	</select>
</mapper> 

3.测试

package com.skymr.mybatis.service;

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

import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.skymr.mybatis.mappers.StudentTMapper;
import com.skymr.mybatis.model.Student;
import com.skymr.mybatis.util.MybatisUtil;

public class StudentTest4 {

	private Logger logger = LoggerFactory.getLogger(StudentTest4.class);
	
	private SqlSession session;
	
	@Before
	public void beforeTest(){
		session = MybatisUtil.openSession();
	}
	@After
	public void afterTest(){
		session.close();
	}
	
	@Test
	public void testSearch(){
		logger.info("测试查询学生");
		StudentTMapper mapper = session.getMapper(StudentTMapper.class);
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("name", "%aaa%");
		map.put("age", 111);
		List<Student> list = mapper.searchStudents(map);
		logger.info(list.toString());
	}
	
}

二.choose,when ,otherwise

Sometimes we don’t want all of the conditionals to apply, instead we want to choose only one case
among many options. Similar to a switch statement in Java, MyBatis offers a choose element.
Let’s use the example above, but now let’s search only on title if one is provided, then only by author
if one is provided. If neither is provided, let’s only return featured blogs (perhaps a strategically list
selected by administrators, instead of returning a huge meaningless list of random blogs).
有些时候我们不想所有的条件都使用到,只想在所有条件中选择一个条件.与java的switch语种相似,Mybatis提供了一个元素.让我们做个例子.
<select id="findActiveBlogLike"
     resultType="Blog">
  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>
上面的例子是引用Mybatis文档.

自己的例子:

	<select id="searchStudents2" resultMap="stuMap" parameterType="map">
		select * from mybatis_student where 1=1
		<choose>
			<when test="searchBy=='name'">
				and name like #{name}
			</when>
			<when test="searchBy=='gradeId'">
				and grade_id=#{gradeId}
			</when>
			<otherwise>
				and age=#{age}
			</otherwise>
		</choose>
	</select>

三.trim, where, set元素

1.当没有条件时,有可能会生成这样的sql

SELECT * FROM BLOG
WHERE

如果不在后边加入 1=1,则应该加上where标签

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
	  <if test="state != null">
	    state = #{state}
	  </if>
  </where>
</select>
改成这样就可以避免以上情况.
2.还有这种情况

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’
需要去年多余的and /or

	<select id="searchStudents3" resultMap="stuMap" parameterType="map">
		select * from mybatis_student 
		<trim prefix="WHERE" prefixOverrides="AND|OR">
			<if test="name!=null">
				and name like #{name}
			</if>
			<if test="age!=null">
				and age=#{age}
			</if>
		</trim>
	</select>

同样,update set语句也会出现多余的","的问题

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

也可以使用trim修改

<update id="updateAuthorIfNecessary">
  update Author
    <trim prefix="SET" suffixOverrides=",">
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </trim>
  where id=#{id}
</update>
四.foreach元素

这是一个非常有用的动态sql元素,用来遍历集合,常应用于IN语句中,例:

IN condition. For example:
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

foreach元素非常强大,它允许你指定一个集合,声明item和index变量,在元素内部使用.生成有"开始/结尾/分隔符"的字符串,这个元素非常智能,它不会不小心添加额外的分隔符.

记住,你可以把一个List实例或者一个数组当作参数传递到MyBatis.当你这样做了,MyBatis会自动放到一个Map里.List实例会以"list"作为Key值,数组实例会以"array"作为Key值.

foreach元素的属性主要有 item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名.
index指 定一个名字,用于表示在迭代过程中,每次迭代到的位置.
open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔 符.
close表示以什么结束.

上面的例子生成的sql相当于

  SELECT *
  FROM POST P
  WHERE ID in (?,?,?)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值