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, limit, group by等场所。
假设我们使用#{} 来指定order by字段,比如
select * from student order by #{xCode},
那么产生的SQL为
select * from student order by ?, 替换值后为
select * from student order by ‘xCode’
Mybatis对xCode加了引号导致排序失败

2、Spring环境用Mybatis-Spring的接口而不是Mybatis的原生接口

spring 环境使用mybatis-spring的好处有:
1)我们可以使用Sping的声明式事务处理模型(@Transactional),而不用手动回归事务。
2)mybatis-spring会优雅的关闭SqlSession,而不用手动关闭
3)可以将数据库连接池交给spring管理,当程序停止的时候,spring会合适的关闭连接

3、返回Map<ID, Entity>而不是List便于查找

有时太多的表连接(join)性能太差,我们会将该SQL拆为多个SQL,然后在代码中组装起来。比如学生表和班级表,需要查询的结果为”学号,班级,姓名”,我们可以先查询“学号,班级ID,姓名”以及“班级ID,班级名次”,我们可以在查询班级表的时候返回Map<班级ID, 班级>, 然后迭代学生表的结果集,用班级ID到Map<班级ID, 班级>中查找对应的班级信息,然后用班级名称替换班级ID。
接口声明为SqlSession.selectMap(String statement, String mapKey)

4、使用Map封装查询的结果

有时我们厌倦了为每个查询写一个Entity类,这时Map开始发挥它的功效。
对于要返回“学号,班级,姓名”结果的查询,可以这样写Mapper:

 
1
2
3
4
5
<select id="selectStudent">
    select s.code as sNo , s.name as sName, c.name as cName
    from xStudent s, xClass c
    where s.cID = c.ID
</select>

如下声明我们的dao方法:

 
1
2
3
public List<Map<String, Object>> selectStudent(Map<String, Object> parameter) {
    return getSqlSession().selectList(getStatement("selectStudent"), parameter);
}

如果要将该查询结果转为JSON字符串返回,那么我们就可以直接将List<Map<String, Object>转为JSON,逻辑层不需要任何代码。
如果返回的结果集需要按select中的字段顺序返回,那么将resultType=”Java.util.HashMap” 换为resultType=”java.util.LinkedHashMap”

5、使用Map封装查询结果时注意数据的类型映射

对于如下的Mapper

 
1
2
3
4
<select id="selectStudent">
    select s.code as sNo , concat(s.firstName, s.lastName) as sName
    from xStudent s
</select>

Mybatis会傻傻的将sName的数据类型映射为byte[], 因为我们没有提供entity,mybatis也不知道我们想要什么类型,而sName是计算出来的值,mybatis也没有办法从数据库中获取字段的值,所以它就将其封装为byte[],解决办法很简单,加一个cast 函数

 
1
2
3
4
<select id="selectStudent">
    select s.code as sNo , cast(concat(s.firstName, s.lastName) AS CHAR) as sName
    from xStudent s
</select>

6、正确的配置Mybatis 的Log

1)一个应用一般会使用很多的jar,各个jar依赖的log 实现不一样,Mybatis查找Log的顺序为(SLF4J,Apache Commons Logging,Log4j 2,Log4j,JDK logging),如果classpath中有slf4j记得添加相应的桥接jar,比如slf4j-log4j。许多web 服务器的classpath 会含有Apache Commons Logging,因此如果要使用Log4j,要么使用SLF4J桥接Log4j,要么在配置中强制指定使用Log4J。

 
1
2
3
4
5
6
7
<configuration>
<settings>
...
<setting name="logImpl" value="LOG4J"/>
...
</settings>
</configuration>

7、警惕Mybatis的Foreach的的副作用

对于如下SQL:
假设有如下的mapper:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id=”testForeach”  parameterType=”map”  resultType=”Student”>
    Select * from student
    <where>
    <if test=”ID != null and ID != ‘’ ”>
        ID = #{ID}
    </if>
    <if test=” IDArr != null and IDArr.size()>0”>
        And ID IN
            <foreach collection="IDArr" open="("
        separator="," close=")" item="ID">
        ${ID}
            </foreach>
        </if>
</where>
</select>

当我们传入的IDArr时,最后产生的SQL为:
Select * from student where ID = ‘998’ AND ID IN ( ‘123’, ’234’,…..,’998’)
解决办法:
解决办法有
1) 将红色的ID 换成别的名称,比如“item”。
2) 这两个if 是对同一个字段判断,改为choose… when 结构

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id=”testForeach”  parameterType=”map”  resultType=”Student”>
    Select * from student
    <where>
    <choose>
        <when test=”ID != null and ID != ‘’ ”>
            ID = #{ID}
        </when>
        <when test=” IDArr != null and IDArr.size()>0”>
            And ID IN
            <foreach collection="IDArr" open="("
                separator="," close=")" item="ID">
                ${ID}
            </foreach>
        </when>
</choose>
</where>

8、使用原生的SQL操作数据以提高效率

对于一次插入多条数据,将其组装成 insert into xxx values (), () ()格式一次插入多行数据往往能极大的提高性能。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public int execute(String sql) {
    int affectedCount = 0;
    Connection conn = null;
    Statement stm = null;
    try {
        conn = getSqlSession().getConnection();
        stm = conn.createStatement();
        stm.execute(sql);
        affectedCount = stm.getUpdateCount();
    } catch (SQLException e) {
        throw new RuntimeException(“execute[" + sql + "] failed”);
    } finally {
        try{
        if(stm != null &amp;&amp; !stm.isClosed()) {
        stm.close();
        }
        //conn will be released by mybatis framework
        } catch(SQLException e) {
        }
    }
    return affectedCount;
}

9、警惕MyBatis封装数据时性能损耗

对于如下的mapper

 
1
2
3
4
5
6
7
<select id="test" resultType="Student">
    select s.code, s.firstName,
    s.lastName, s.birthDate, s.sex, s.checkIn, s.phoneNumber,
    s.classNo
    from student
    where ...
</select>

在一个批处理程序中循环的调用了该方法250次,每次返回大概1w条记录,发现这个程序运行的很慢,用jrofiler 查看各个方法耗费的时间,居然80%的时间花在了student的setter上了,在这个过程中大概产生了250w个对象,而mybatis是利用发射封装Entity,代码大致如下:

 
1
2
3
4
5
6
Class c= Class.forName("cn.javacoder.testmybatis.Student");
Object o = c.newInstance();
for(each colum) {
Method m = c.getMethod("get" + colum);
m.invoke(o, value);
}

解决的办法是让返回的行数和返回的字段尽量的少。

MyBatis学习总结_14_Mybatis使用技巧总结的更多相关文章

  1. MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作(转载)

    本文转载自:http://www.cnblogs.com/jpf-java/p/6013540.html 上一篇博文MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybati ...

  2. MyBatis学习总结(八)——Mybatis3.x与Spring4.x整合(转载)

      孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(八)--Mybatis3.x与Spring4.x整合 一.搭建开发环境 1.1.使用Maven创建Web项目 执行如下命令: m ...

  3. MyBatis学习总结(七)——Mybatis缓存(转载)

      孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(七)--Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的 ...

  4. (原创)mybatis学习二,spring和mybatis的融合

    mybatis学习一夯实基础 上文介绍了mybatis的相关知识,这一节主要来介绍mybaits和spring的融合 一,环境搭建 1,jar包下载,下载路径为jar包 2,将包导入到java工程中 ...

  5. (原创)mybatis学习一,夯实基础

    一,what?(是什么) MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可 ...

  6. MyBatis学习--简单的增删改查

    jdbc程序 在学习MyBatis的时候先简单了解下JDBC编程的方式,我们以一个简单的查询为例,使用JDBC编程,如下: Public static void main(String[] args) ...

  7. MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作

    上一篇博文MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对u ...

  8. 【Todo】Mybatis学习-偏理论

    之前写过好几篇Mybatis相关的文章: http://www.cnblogs.com/charlesblc/p/5906431.html  <SSM(SpringMVC+Spring+Myba ...

  9. MyBatis学习系列三——结合Spring

    目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...

随机推荐

  1. Iphone5s 通话质量差 问题解决

    从某段时间开始,我的手机出现通话质差的情况.而且与信号电平有密切关系,只要覆盖稍差的地方,通话就劣化. 具体症状是我时常听不清对方说话,但对方能够清晰听到我说话. 因为本人也是从事无线网络优化软件产品 ...

  2. Android -- NDK开发入门

    第一步,建立一个普通的Android项目HelloNDK,然后在与src同一级的目录下新建一个jni目录: 第二步,在jni目录下新建一个hello_ndk.c文件,代码如下: #include &l ...

  3. 启动级别:init 0,1,2,3,4,5,6

    这是个很久的知识点了,只是自己一直都迷迷糊糊的,今天在翻出来好好理解下.. 0:停机 1:单用户形式,只root进行维护 2:多用户,不能使用net file system 3:完全多用户 5:图形化 ...

  4. 新 四则运算题目 C++

    源代码: #include <stdlib.h>#include <iostream.h>#include <conio.h>#include <time.h ...

  5. jQuery中ready与load事件

    jQuery中ready与load事件(来自慕课网) jQuery有3种针对文档加载的方法 $(document).ready(function() { // ...代码... }) //docume ...

  6. android开发 textview根据字数长度自动调整字体大小

    需求:根据输入的值实时显示到textview中预览,但是字体大小是要自动适配的 网上有一个代码,但是在我这里不能用,注意方法:refitText  注释掉的是之前的代码 import com.cars ...

  7. JavaScript的DOM操作(1)

    1.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档:对象是指文档中每个元素:模型是指抽象化的东西. 2.Window对象操作 一.属性和方法: 属性(值或者子对象): op ...

  8. c++ dirname() basename()

    http://linux.about.com/library/cmd/blcmdl3_dirname.htm #include <iostream> #include <libgen ...

  9. CSS3动画制作的简单示例

    CSS3 大大强化了制作动画的能力,但是如果要做出图案比较复杂的动画,选择 GIF 依然是一个不错的选择.今天给大家介绍一个使用 CSS animation 配合雪碧图(CSS sprite)来制作动 ...

  10. wireshark常用的过滤命令

    我们使用wireshark抓包,却不知道如何分析这些包,也无法从海量的包中提取自己需要的数据,下面简单介绍下wireshark的过滤规则. 过滤源ip.目的ip.在wireshark的过滤规则框Fil ...