前言

  最近比较松懈,下班回家后也懒得学习了。今晚实在是看不下去了,争取时间学习。社会上有这么多的资源,就看谁能抢的多吧。今天就说说MyBatis的动态SQL吧

正文

  动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。比如:

<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>

如果这些条件没有一个能匹配上将会怎样?最终这条 SQL 会变成这样:

SELECT * FROM BLOG
WHERE

这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

这个查询也会失败。这个问题不能简单的用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不想再这样去写了。

MyBatis 有一个简单的处理,这在90%的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能得到想要的效果:

<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>

where 元素知道只有在一个以上的if条件有值的情况下才去插入“WHERE”子句。而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除。

好了,上面都是摘自MyBatis官网,说明了动态sql在使用中存在的问题,那我就以where为例,跑一个小程序,还是基于前面几节中使用到的表。

<select id="getUserByObjInDynamicMethod" parameterType="org.tonny.entity.User" resultType="org.tonny.entity.User">
SELECT * FROM users
<where>
<if test="id != null">
id=#{id}
</if>
<if test="name != null">
and name like #{name}
</if> </where>
</select> <select id="getUserByMapInDynamicMethod" parameterType="org.tonny.entity.User" resultType="org.tonny.entity.User">
SELECT * FROM users
<where>
<if test="id != null">
id=#{id}
</if>
<if test="name != null">
and name like #{name}
</if> </where>
</select>

这部分配置与上面的一样,使用了where标签。对应的Java代码如下:

@Test
public void getUserByObjInDynamicMethod()
{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 映射sql的标识字符串
String sql = "org.tonny.mapper.UsersMapper.getUserByObjInDynamicMethod";
User user = new User();
user.setId(1);
user.setName("%nny%");
user.setAge(30);
List<User> userList = sqlSession.selectList(sql, user);
sqlSession.close();
System.out.println(userList);
} @Test
public void getUserByMapInDynamicMethod()
{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 映射sql的标识字符串
String sql = "org.tonny.mapper.UsersMapper.getUserByObjInDynamicMethod";
Map<String,Object> map = new HashMap<String, Object>();
map.put("id", 1);
map.put("name", "%nny%");
List<User> userList = sqlSession.selectList(sql, map);
sqlSession.close();
System.out.println(userList);
}

这样就可以查出来了。对了,为了可以在控制台查看MyBatis的SQL,需要在mybatis.xml增加配置信息:

<!-- 设置日志打印 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

这样就可以看到输出的sql语句了。测试结果:

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 25193812.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1806d54]
==> Preparing: SELECT * FROM users WHERE id=? and name like ?
==> Parameters: 1(Integer), %nny%(String)
<== Columns: id, NAME, age
<== Row: 1, Tonny Chien, 25
<== Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1806d54]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1806d54]
Returned connection 25193812 to pool.
[User [id=1, name=Tonny Chien, age=25]]

还要介绍一下set标签,它对应update中的set

<update id="updateUserByMapInDynamicMethod" parameterType="java.util.Map">
UPDATE users
<set>
<if test="name != null">
name = #{name},
</if>
<if test="age != null">
age = #{age}
</if>
</set>
<where>
<if test="id != null">
id=#{id}
</if>
<if test="age != null">
<![CDATA[
and age > #{age}
]]>
</if>
</where>
</update>

Java测试代码如下:

@Test
public void updateUserByMapInDynamicMethod()
{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 映射sql的标识字符串
String sql = "org.tonny.mapper.UsersMapper.updateUserByMapInDynamicMethod";
Map<String,Object> map = new HashMap<String, Object>();
map.put("id", 1);
map.put("age", 20);
map.put("name", "北堂一刀");
int result = sqlSession.update(sql, map);
sqlSession.commit();
sqlSession.close();
System.out.println(result);
}

执行结果:

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 30587315.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
==> Preparing: UPDATE users SET name = ?, age = ? WHERE id=? and age > ?
==> Parameters: 北堂一刀(String), 20(Integer), 1(Integer), 20(Integer)
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1d2b9b3]
Returned connection 30587315 to pool.
1

后记

就写到这儿吧,下次再详细些,休息了。

MyBatis学习(四)的更多相关文章

  1. (原创)mybatis学习四,利用mybatis自动创建代码

    在使用mybatis的过程中,我们可以直接利用MyBatis生成器自动生成实体类.DAO接口和Mapping映射文件,然后copy到工程中即可 需要的jar包如下 下载路径如下:下载jar包 其中的g ...

  2. mybatis学习四 mybatis的三种查询方式

    <select id="selAll" resultType="com.caopeng.pojo.Flower"> select * from fl ...

  3. mybatis 学习四(下) SQL语句映射文件增删改查、参数、缓存

    2.2 select 一个select 元素非常简单.例如: <!-- 查询学生,根据id --> <select id="getStudent" paramet ...

  4. mybatis 学习四 (上)resutlMap

    SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: ...

  5. mybatis 学习四 源码分析 mybatis如何执行的一条sql

    总体三部分,创建sessionfactory,创建session,执行sql获取结果 1,创建sessionfactory      这里其实主要做的事情就是将xml的所有配置信息转换成一个Confi ...

  6. MyBatis学习 之 四、MyBatis配置文件

    目录(?)[-] 四MyBatis主配置文件 properties属性 settings设置 typeAliases类型别名 typeHandlers类型句柄 ObjectFactory对象工厂 pl ...

  7. 【转】MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突

    [转]MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体 ...

  8. mybatis 学习笔记(四):mybatis 和 spring 的整合

    mybatis 学习笔记(四):mybatis 和 spring 的整合 尝试一下整合 mybatis 和 spring. 思路 spring通过单例方式管理SqlSessionFactory. sp ...

  9. (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合

    http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...

随机推荐

  1. Mysql语句示例

    Mysql语句示例 最常用 sql 语句总结 前言 Mysql 是数据库开发使用的主要平台之一.sql 的学习掌握与使用是数据库开发的基础,此处展示详细sql 语句的写法,及各种功能下的 sql 语句 ...

  2. WebAssembly,可以作为任何编程语言的编译目标,使应用程序可以运行在浏览器或其它代理中——浏览器里运行其他语言的程序?

    Mozilla.谷歌.微软和苹果已经决定开发一种面向Web的二进制格式.该格式名为WebAssembly,可以作为任何编程语言的编译目标,使应用程序可以运行在浏览器或其它代理中. 几年前,我们在Inf ...

  3. codeforces 690D2 D2. The Wall (medium)(组合数学)

    题目链接: D2. The Wall (medium) time limit per test 2 seconds memory limit per test 256 megabytes input ...

  4. BZOJ_5311_贞鱼_决策单调性+带权二分

    BZOJ_5311_贞鱼_决策单调性+带权二分 Description 众所周知,贞鱼是一种高智商水生动物.不过他们到了陆地上智商会减半. 这不?他们遇到了大麻烦! n只贞鱼到陆地上乘车,现在有k辆汽 ...

  5. 【旧文章搬运】分析了一下360安全卫士的HOOK

    原文发表于百度空间及看雪论坛,2009-10-08 看雪论坛地址:https://bbs.pediy.com/thread-99128.htm 看时间,09年的国庆节基本上就搞这玩意儿了...==== ...

  6. HDU5145:5145 ( NPY and girls ) (莫队算法+排列组合+逆元)

    传送门 题意 给出n个数,m次访问,每次询问[L,R]的数有多少种排列 分析 \(n,m<=30000\),我们采用莫队算法,关键在于区间如何\(O(1)\)转移,由排列组合知识得到,如果加入一 ...

  7. Codeforces732E Sockets

    首先检测有木有和Computer匹配的Socket,如果有则将其匹配. 然后将所有没有匹配的Socket连上Adapter,再去检测有木有Computer与Socket匹配. 重复这个操作31次,所有 ...

  8. 洛谷P2585 [ZJOI2006]三色二叉树(树形dp)

    传送门 设$dp[u][i]$表示点$u$颜色为$i$时最多(最少)的绿点个数(这里用$0$表示绿点) 然后直接用树形dp就可以了 记得把情况讨论清楚 //minamoto #include<b ...

  9. P1251 递推专练3

    递推专练3 描述 Description 圆周上有N个点.连接任意多条(可能是0条)不相交的弦(共用端点也算相交)共有多少种方案? 输入格式 Input Format 读入一个数N.<=N< ...

  10. class JsonItemExporter(BaseItemExporter):

    class JsonItemExporter(BaseItemExporter):这个类的实现和几年前的实现有了点小变化,主要就是是否添加换行