您的位置:首页 > 数据库

MyBatis学习笔记(六)动态sql

2015-08-31 19:59 591 查看
在一些情况下,如查询参数不确定时,需要用到动态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 (?,?,?)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: