探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制
Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南
自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理
版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn.net/lfdfhl
MyBatis可利用动态SQL极大的简化SQL语句的拼接。
在此介绍几种MyBatis中常用的动态SQL
where和if
还记得我们之前有一个查询学生的例子么?
<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
SELECT * FROM student WHERE gender=#{studentCustom.gender} and name like '%${studentCustom.name}%'
</select>
猛地一看这个SQL没啥问题,但是仔细一想又不对,studentCustom有没有可能为null呢?studentCustom.gender和studentCustom.name有没有可能为null呢?当然是有的,那么我们可以怎么处理一下呢?此时就可以用<where>和<if>,请看:
<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
SELECT * FROM student
<where>
<if test="studentCustom!=null">
<if test="studentCustom.gender!=null">
and gender=#{studentCustom.gender}
</if>
<if test="studentCustom.name!=null">
and name like '%${studentCustom.name}%'
</if>
</if>
</where>
</select>
在此利用标签<where>和<if>对应了某些查询条件为null的情况。有人或许有疑问,如果两个查询条件都满足的话在这个sql中岂不是有两个and了?甭担心,这种情形下MyBatis会自动删除掉掉第一个and
sql
其实,我们还可以把刚才这个例子继续优化一下利用<sql>提取出<if>作为sql片段从而提高代码的复用性
<sql id="findStudentList_if">
<if test="studentCustom!=null">
<if test="studentCustom.gender!=null">
and gender=#{studentCustom.gender}
</if>
<if test="studentCustom.name!=null">
and name like '%${studentCustom.name}%'
</if>
</if>
</sql>
然后在查询语句中引用该sql片段即可
<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
SELECT * FROM student
<where>
<include refid="findStudentList_if"></include>
</where>
</select>
foreach
来看一种需求:查询出id为2、4、7的学生信息,我们可以这么写sql
SELECT * FROM student WHERE (id=2 OR id=4 OR id=7)
那么这个sql在MyBatis里又该怎么写呢?
在此可采用<foreach>标签来拼装这个条件(id=2 OR id=4 OR id=7)
首先,我们在StudentQueryVO中定义一个字段idsList用于传递这几个id值
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
package cn.com;
import java.util.List;
//自定义的包装类型的pojo
public class StudentQueryVO {
private List<Integer> idsList;
//用户查询条件
private StudentCustom studentCustom;
public StudentCustom getStudentCustom() {
return studentCustom;
}
public void setStudentCustom(StudentCustom studentCustom) {
this.studentCustom = studentCustom;
}
public List<Integer> getIdsList() {
return idsList;
}
public void setIdsList(List<Integer> idsList) {
this.idsList = idsList;
}
//其他查询条件,比如教师,课程,学校等等
}
再来看mapper.xml
<sql id="findStudentList_ids_if">
<if test="idsList!=null">
<foreach collection="idsList" item="student_id" open="(" close=")" separator="OR">
id=#{student_id}
</foreach>
</if>
</sql>
<select id="findStudentList" parameterType="cn.com.StudentQueryVO" resultType="cn.com.StudentCustom">
SELECT * FROM student
<where>
<include refid="findStudentList_ids_if"></include>
</where>
</select>
重点来看这个<foreach>标签
- collection表示pojo中的集合
- item表示遍历时集合中每个元素
- open表示组拼后的语句的开头
- close表示组拼后的语句的结尾
- separator表示每个部门的连接符
最后来看测试代码
@Test
public void findStudentList() throws IOException {
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
StudentQueryVO studentQueryVO=new StudentQueryVO();
List<Integer> idsList=new ArrayList<Integer>();
idsList.add(2);
idsList.add(4);
idsList.add(7);
studentQueryVO.setIdsList(idsList);
List<StudentCustom> studentList = studentMapper.findStudentList(studentQueryVO);
for (int i = 0; i <studentList.size(); i++) {
StudentCustom sc = studentList.get(i);
System.out.println(sc);
}
sqlSession.commit();
sqlSession.close();
}
其实,这些动态SQL并不难,也不需要死记硬背。但是要把握住总的原则和目标:利用动态SQL拼装成原始的sql语句。在实际开发时也可以先写出原始sql语句再写到mapper.xml中