Mybatis practise

Mybatis log机制源码分析

Dec 7, 2014 | | Say something

本文先介绍当mybatis 使用log4j时的配置原理,然后介绍如何在运行时动态的开关log!!! 无论使用哪一种ORM框架,我们都希望在开发的时候能打印出最后产生的SQL语句,网上有很多关于mybatis配置的文章,都是相互转载,而且让人郁闷的是都是基于ibatis时代的配置。javacoder.cn博主秉着知其然,必知其所以然的原则,决定对其源码进行一番分析。揭开log4j的日志到底是如何影响sql输出的。本文使用slf4j桥接log4j的日志实现,这样即使classpath下有别的日志jar,也能正常输出。文件结尾处有我调试跟踪时使用的demo,该demo基于maven,导入Eclipse就可以调试了,欢迎下载!! 1)假设classpath下有如下内容的log4j.properties

请求http://localhost:8080/testoom/test,发现控制台的输出为 DEBUG [http-bio-8080-exec-1] – ooo Using Connection [jdbc:mysql://localhost:3306/test UserName=root@localhost, MySQLDriver] DEBUG [http-bio-8080-exec-1] – ==> Preparing: select * from application DEBUG [http-bio-8080-exec-1] – ==> Parameters: 第一行是在org.apache.ibatis.logging.jdbc.ConnectionLogger.ConnectionLogger(Connection conn, Log statementLog)中输出的 第二行是在Object org.apache.ibatis.logging.jdbc.ConnectionLogger.invoke(Object proxy, Method method, Object[] params)throws Throwable中输出的 第三行是在Object org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(Object proxy, Method method, Object[]params) throws Throwable中输出的。 接下来我们详细分析ConnectionLogger(Connection conn, Log statementLog)方法

跟踪isDebugEnabled(), […more]

Mybatis 使用技巧总结

Sep 11, 2014 | | Say something

目录: 1、区分 #{} 和 ${}的不同应用场景 2、spring环境用mybatis-spring 的接口而不是Mybatis的原生接口 3、返回Map<ID, Entity>而不是List便于查找 4、使用Map封装查询的结果 5、使用Map封装查询结果时注意数据的类型映射 6、正确的配置Mybatis 的Log 7、警惕Mybatis的foreach的的副作用 8、使用原生的SQL操作数据以提高效率 9、警惕MyBatis封装数据时性能损耗 1、 区分 #{} 和 ${}的不同应用场景 1)#{} 会生成预编译SQL,会正确的处理数据的类型,而${}仅仅是文本替换。 对于SQL: select * from student where xCode = ‘S123456’; 如果使用#{} 那么生成的SQL为: select * from student where xCode = ? 传的值为’S123456’; 如果使用${} 那么生成的SQL为:select * from student where xCode = S123456 如果xCode的数据类型为varchar,那么使用${}就会报错。 2)${}一般用在order by, […more]

警惕Mybatis的foreach的的副作用

Sep 10, 2014 | | Say something

假设有如下的mapper:

这个动态SQL很简单,如果参数中有ID字段,那么将SQL组装为:

如果参数中有IDArr,那么将SQL组装成

计划的很完美,但实际却不是这样的,当有参数IDArr时,组装成的SQL却为:

解决办法有 1)  将红色的ID 换成别的名称,比如“item”。 2)  这两个if 是对同一个字段判断,改为choose… when 结构

在Mybatis中一条SQL插入多行数据

Aug 22, 2014 | | Say something

由于批量插入时用一个sql比在一个事务中用多个sql要快,因为这样可以减少web服务器和数据库服务器的网络通信时间, 假设entity如下: class Entity { private int id; private String name; private java.util.Date date; } 在mybatis的mapper 文件中,我的代码如下 <insert id=”insert” > insert into xEntity values <foreach collection=”list” item=”item” separator=”,”> (#{id},#{name}, #{date}) </foreach> </insert> 由于我们使用mybatis的#{}语义,它会生成预编译的sql,然后填充值 insert into xEntity values(?,?,?),(?,?,?)… 对于这种一个sql插入多条数据的sql预编译是没有任何好处的,每次插入的长度都不一样,没有机会使用预编译带来的好处 将mapper中的sql 改为: <insert id=”insert” > insert into xEntity values <foreach collection=”list” item=”item” separator=”,”> (${id},${name}, ${date}) </foreach> </insert> […more]

Mybatis使用Map代替Entity封装数据

Aug 21, 2014 | | Say something

有时我们厌倦了写entity来封装从数据库查询出来的记录,比如一个关联查询,我们不想为这个查询写一个entity ,因为这个查询可能只使用一次, 这时我们可以使用Map来封装一行的数据,而不是新建一个entity。 我们可以这样写: <select id=”select” resultType=”java.util.HashMap”> Select t.xID, t.xName from student t </select>   这样Mybatis 返回给我们的结果的数据类型为List<Map<String, Object>>,   迭代如下: List<Map<String, Object>> rs = ……. // from mybatis For(Map<String, Object> m: rs) { Integer xID = (Integer)m.get(“xID”); String xName = (String)m.get(“xName”); System.out.println(“id:” + xID + “   xName:” + xName); }   当result Map 关联的是一个Map的list时,我们需要同时指定collection 的ofType […more]

Mybatis Order by 没有生效

Aug 21, 2014 | | Say something

select * from student t order by #{orderString} 传值如下:orderString = “t.xCode Desc” 发现查出来的记录是没有排序的,当把select * from student t order by t.xCode Desc 在命令行直接执行的时候,查询出来的结果是排好序的,google了很久才发现, 对了排序不能用#{} 只能用${} , #{}的语义是产生preparedStatement :上面的SQL预编译后产生的SQL如下: select * from student t order by ? 在运行时将?替换为” t.xCode Desc”, mybatis 会安全的处理类型,产生的最终SQL如下: select * from student t order by ‘t.xCode Desc’ 所以排序失败, 但是该sql能正常运行,至少我在Mysql上执行的结果是这样的,不知是否是mysql 的bug。   ${}直接进行字符串的替换,产生的SQL 为: […more]

mybatis 将concat 结果映射为byte数组‏

Aug 21, 2014 | | Say something

今天写了一个类似这样的SQL SELECT CONCAT(id,’||’, type) as dataId 在mybatis的mapper的resultType=”java.util.HashMap” ,结果将其映射为byte[] , 加一个CAST函数搞定 SELECT CAST(CONCAT(id,’||’, type) AS CHAR) as dataId