动态SQL

何为动态SQL??回顾一下我们之前写的SSH项目中,有多条件查询的情况,如下图

我们当时刚开始做的时候,是需要在Controller中判断SQL是否已经有条件了,因为SQL语句需要拼接起来….这样干的话,就非常容易出错的。

如下的代码,如果有多个条件的话,那么拼接起来很容易出错!


public String listUI() { //查询语句
String hql = "FROM Info i ";
List<Object> objectList = new ArrayList<>(); //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。
if (info != null) {
if (StringUtils.isNotBlank(info.getTitle())) {
hql += "where i.title like ?";
objectList.add("%" + info.getTitle() + "%");
}
}
infoList = infoServiceImpl.findObjects(hql,objectList);
ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
return "listUI";
}

后来,我们觉得这样不好,于是就专门写了一个查询助手类:


package zhongfucheng.core.utils; import java.util.ArrayList;
import java.util.List; /**
* Created by ozc on 2017/6/7.
*/
public class QueryHelper { private String fromClause = "";
private String whereClause = "";
private String orderbyClause = "";
private List<Object> objectList; public static String ORDER_BY_ASC = "asc";
public static String ORDER_BY_DESC = "desc"; //FROM子句只出现一次
/**
* 构建FROM字句,并设置查询哪张表
* @param aClass 用户想要操作的类型
* @param alias 别名
*/
public QueryHelper(Class aClass, String alias) {
fromClause = " FROM " + aClass.getSimpleName() + " " + alias;
}
//WHERE字句可以添加多个条件,但WHERE关键字只出现一次
/**
* 构建WHERE字句
* @param condition
* @param objects
* @return
*/
public QueryHelper addCondition(String condition, Object... objects) {
//如果已经有字符了,那么就说明已经有WHERE关键字了
if (whereClause.length() > 0) {
whereClause += " AND " + condition;
} else {
whereClause += " WHERE" + condition;
}
//在添加查询条件的时候,?对应的查询条件值
if (objects == null) {
objectList = new ArrayList<>();
} for (Object object : objects) {
objectList.add(object);
} return this;
}
/**
*
* @param property 要排序的属性
* @param order 是升序还是降序
* @return
*/
public QueryHelper orderBy(String property, String order) { //如果已经有字符了,那么就说明已经有ORDER关键字了
if (orderbyClause.length() > 0) {
orderbyClause += " , " + property +" " + order;
} else {
orderbyClause += " ORDER BY " + property+" " + order;
}
return this;
} /**
* 返回HQL语句
*/
public String returnHQL() {
return fromClause + whereClause + orderbyClause;
} /**
* 得到参数列表
* @return
*/
public List<Object> getObjectList() {
return objectList;
}
}

这样一来的话,我们就不用自己手动拼接了,给我们的查询助手类去拼接就好了。

而如果我们使用Mybatis的话,就可以免去查询助手类了。因为Mybatis内部就有动态SQL的功能【动态SQL就是自动拼接SQL语句】

动态查询


<!--多条件查询【动态SQL】-->
<!--会自动组合成一个正常的WHERE字句-->
<!--name值会从map中寻找--> <select id="findByCondition" resultMap="studentMap" parameterType="map"> select * from students <where>
<if test="name!=null">
and name=#{name}
</if>
<if test="sal!=null">
and sal &lt; #{sal}
</if>
</where> </select>

查询出来小于9000块的人


public List<Student> findByCondition(String name,Double sal) throws Exception {
//得到连接对象
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
/**
* 由于我们的参数超过了两个,而方法中只有一个Object参数收集
* 因此我们使用Map集合来装载我们的参数
*/
Map<String, Object> map = new HashMap();
map.put("name", name);
map.put("sal", sal);
return sqlSession.selectList("StudentID.findByCondition", map);
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
}
public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
List<Student> students = studentDao.findByCondition(null,9000D);
for (Student student : students) {
System.out.println(student.getId() + "---" + student.getName() + "----" + student.getSal());
} }

动态更新


<!--动态更新-->
<!--不要忘了逗号-->
<update id="updateByConditions" parameterType="map"> update students
<set>
<if test="name!=null">
name = #{name},
</if>
<if test="sal!=null">
sal = #{sal},
</if>
</set>
where id = #{id}
</update>

给出三个更新的字段


public void updateByConditions(int id,String name,Double sal) throws Exception {
//得到连接对象
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
/**
* 由于我们的参数超过了两个,而方法中只有一个Object参数收集
* 因此我们使用Map集合来装载我们的参数
*/
Map<String, Object> map = new HashMap();
map.put("id", id);
map.put("name", name);
map.put("sal", sal);
sqlSession.update("StudentID.updateByConditions", map);
sqlSession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
} public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
studentDao.updateByConditions(2,"haha",500D); }

动态删除



以前我们使用JDBC也好,Hibernate也好,想要批量删除的时候,总是使用的是循环删除。而我们现在使用的是Mybatis,SQL语句是自己写的。所以我们可以写下如下的SQL来进行删除


delete from students where id in (?,?,?,?);

而我们的Mybatis又支持动态SQL,所以删除起来就非常方便了!


<delete id="deleteByConditions" parameterType="int"> <!-- foreach用于迭代数组元素
open表示开始符号
close表示结束符合
separator表示元素间的分隔符
item表示迭代的数组,属性值可以任意,但提倡与方法的数组名相同
#{ids}表示数组中的每个元素值
-->
delete from students where id in
<foreach collection="array" open="(" close=")" separator="," item="ids">
#{ids}
</foreach> </delete>

删除编号为2,3,4的记录

    public void deleteByConditions(int... ids) throws Exception {
//得到连接对象
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
/**
* 由于我们的参数超过了两个,而方法中只有一个Object参数收集
* 因此我们使用Map集合来装载我们的参数
*/
sqlSession.delete("StudentID.deleteByConditions", ids);
sqlSession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
} public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
studentDao.deleteByConditions(2,3,4); }

动态插入

我们要想动态插入的话,就比其他的DML语句稍微复杂一点,因为它有两部分是不确定的,平常的SQL语句是这样的:


insert into student(id,name,sal) values(?,?,?)

SQL代码块是不能像之前那样帮我们自动去除多余的逗号的,因此我们需要使用trim标签来自己手动去除…

编写insertSQL语句的时候,不要忘了写()括号。


<!--SQL片段默认是不帮我们自动生成合适的SQL,因此需要我们自己手动除去逗号-->
<sql id="key">
<trim suffixOverrides=",">
<if test="id!=null">
id,
</if> <if test="id!=null">
name,
</if> <if test="id!=null">
sal,
</if>
</trim>
</sql> <sql id="value">
<trim suffixOverrides=",">
<if test="id!=null">
#{id},
</if> <if test="id!=null">
#{name},
</if> <if test="id!=null">
#{sal},
</if>
</trim>
</sql>
<!--动态插入-->
<insert id="insertByConditions" parameterType="zhongfucheng.Student"> insert into students (<include refid="key"/>) values
(<include refid="value"/>) </insert>

测试三个不同内容的数据


public void insertByConditions(Student student) throws Exception {
//得到连接对象
SqlSession sqlSession = MybatisUtil.getSqlSession();
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
sqlSession.insert("StudentID.insertByConditions", student);
sqlSession.commit();
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
} public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDao();
studentDao.insertByConditions(new Student(55, null, null));//name和sal为空 studentDao.insertByConditions(new Student(66, "haxi", null));//sal为空
studentDao.insertByConditions(new Student(77, null, 3999d));//name为空 }

Mybatis第三篇【动态SQL】的更多相关文章

  1. MyBatis(三)动态SQL与缓存

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.动态SQL语句 准备工作: public class User { private int id; ...

  2. Mybatis(三)动态sql语句

    动态sql语句操作 1.MyBatis中#{ }和${ }的区别 在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析.mybatis 为我们提供了两种支 ...

  3. MyBatis学习 之 三、动态SQL语句

    目录(?)[-] 三动态SQL语句 selectKey 标签 if标签 if where 的条件判断 if set 的更新语句 if trim代替whereset标签 trim代替set choose ...

  4. Mybatis学习系列(三)动态SQL

    在mapper配置文件中,有时需要根据查询条件选择不同的SQL语句,或者将一些使用频率高的SQL语句单独配置,在需要使用的地方引用.Mybatis的一个特性:动态SQL,来解决这个问题. mybati ...

  5. MyBatis学习总结_11_MyBatis动态Sql语句

    MyBatis中对数据库的操作,有时要带一些条件,因此动态SQL语句非常有必要,下面就主要来讲讲几个常用的动态SQL语句的语法 MyBatis中用于实现动态SQL的元素主要有: if choose(w ...

  6. MyBatis 注解配置及动态SQL

      一.注解配置 目前MyBatis支持注解配置,用注解方式来替代映射文件,但是注解配置还是有点不完善,在开发中使用比较少,大部分的企业还是在用映射文件来进行配置.不完善的地方体现在于当数据表中的字段 ...

  7. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)——动态SQL

  8. SSM框架之Mybatis(6)动态SQL

    Mybatis(6)动态SQL 1.动态SQL 出现原因:有些时候业务逻辑复杂时,我们的 SQL 是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了 1.1.if标签 我们根据实体类的不 ...

  9. Spring mybatis源码篇章-动态SQL节点源码深入

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-动态SQL基础语法以及原理 前话 前文描述到通过mybatis默认的解析驱动类org.apache.ibat ...

随机推荐

  1. Objective-C写出Json文件(可作配置文件)

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #008f00 } span. ...

  2. org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'username' not found. Available parameters are [1, 0, param1, param2]

    Spring+mybatis错误:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.bi ...

  3. 家中路由添加静态IP映射(一)

    登录路由器配置页面,选择更多功能来添加IP和MAC地址映射关系

  4. C# 实例练习——字符串处理(第三天)

    1.  编写程序将IP地址分解后输出(将IP地址中的点(.)去掉,替换成空格符),如:132.123.4替换后为132  123   4. Console.WriteLine("请输入您电脑 ...

  5. linux下FTP服务器搭建教程1

    你买了个主机就像是买了块地皮,搭建FTP就像是盖房子,我在地皮上建房子,然后创建的用户就像是钥匙,我给谁钥匙(权限),谁就可以到我家去玩,去放东西,拿东西. 虽然我们买不起现实的房子,但是我们可以买互 ...

  6. 201671010133 2016-2017-2 《java程序设计》 初学java!

    新学期伊始,我心中既充满了期待和希望,又有些许激动和感慨.期待的是即将接触许多新的知识,期待未来比过去过的更加踏实有趣,期待遇到更好的人和事等等.当然,面对从未了解过的新事物时,我想每个人的想法都大致 ...

  7. [2017-07-18]logstash配置示例

    提醒 /etc/logstash/conf.d/下虽然可以有多个conf文件,但是Logstash执行时,实际上只有一个pipeline,它会将/etc/logstash/conf.d/下的所有con ...

  8. css 禁止长按保存功能

    *{-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;} 或者指定某个元 ...

  9. C语言运算符运算顺序判断实例1

    程序1 #include <stdio.h> int main(void) { , j = , k = ; printf("%d\n", --j > i & ...

  10. Java 强引用 软引用 弱引用 虚引用详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt393 众所周知,java中是JVM负责内存的分配和回收,这是它的优点(使用方 ...