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
publicList<Map<String,Object>>selectStudent(Map<String,Object>parameter){
    returngetSqlSession().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
<selectid="selectStudent">
    selects.codeassNo,cast(concat(s.firstName,s.lastName)ASCHAR)assName
    fromxStudents
</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
<selectid=”testForeach”  parameterType=”map”  resultType=”Student”>
    Select*fromstudent
    <where>
    <iftest=”ID!=nullandID!=‘’”>
        ID=#{ID}
    </if>
    <iftest=”IDArr!=nullandIDArr.size()>0”>
        AndIDIN
            <foreachcollection="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
publicintexecute(Stringsql){
    intaffectedCount=0;
    Connectionconn=null;
    Statementstm=null;
    try{
        conn=getSqlSession().getConnection();
        stm=conn.createStatement();
        stm.execute(sql);
        affectedCount=stm.getUpdateCount();
    }catch(SQLExceptione){
        thrownewRuntimeException(“execute["
+ sql + "]failed”);
    }finally{
        try{
        if(stm!=null&amp;&amp;!stm.isClosed()){
        stm.close();
        }
        //conn will be released
by mybatis framework
        }catch(SQLExceptione){
        }
    }
    returnaffectedCount;
}

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
Classc=Class.forName("cn.javacoder.testmybatis.Student");
Objecto=c.newInstance();
for(eachcolum){
Methodm=c.getMethod("get"+colum);
m.invoke(o,value);
}

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

MyBatis学习总结(14)——Mybatis使用技巧总结的更多相关文章

  1. mybatis学习笔记(14)-查询缓存之中的一个级缓存

    mybatis学习笔记(14)-查询缓存之中的一个级缓存 标签: mybatis mybatis学习笔记14-查询缓存之中的一个级缓存 查询缓存 一级缓存 一级缓存工作原理 一级缓存測试 一级缓存应用 ...

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

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

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

    [转]MyBatis学习总结(七)——Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualC ...

  4. 【转】MyBatis学习总结(一)——MyBatis快速入门

    [转]MyBatis学习总结(一)——MyBatis快速入门 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC ...

  5. 转:MyBatis学习总结(Mybatis总结精华文章)

    http://www.cnblogs.com/xdp-gacl/tag/MyBatis%E5%AD%A6%E4%B9%A0%E6%80%BB%E7%BB%93/ 当前标签: MyBatis学习总结   ...

  6. Mybatis学习笔记14 - 动态sql之foreach标签

    一.查询给定集合中员工id对应的所有员工信息 示例代码: 接口定义: package com.mybatis.dao; import com.mybatis.bean.Employee; import ...

  7. MyBatis 学习记录5 MyBatis的二级缓存

    主题 之前学习了一下MyBatis的一级缓存,主要涉及到BaseExecutor这个类. 现在准备学习记录下MyBatis二级缓存. 配置二级缓存与初始化发生的事情 首先二级缓存默认是不开启的,需要自 ...

  8. Mybatis学习笔记(一) —— mybatis介绍

    一.Mybatis介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名 ...

  9. Mybatis学习第一天——Mybatis的安装配置以及基本CURD操作

    1.Mybatis下载 Mybatis是开源的持久层框架,能够度jdbc进行简单的封装,但其并不是完全的ORM(Object Relational Mapping,对象关系映射),无法脱离数据库进行适 ...

  10. Mybatis学习笔记(八) —— Mybatis整合spring

    一.整合思路 1.SqlSessionFactory对象应该放到spring容器中作为单例存在. 2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象. 3.Mapper代 ...

随机推荐

  1. js预编译和函数执行

    javascript 执行过程 1.语法检测(有没有基本的语法错误,例如中文,关键字错误...)2.词法分析(预编译) (1)创建全局GO(global object)对象 (2)对var声明的变量进 ...

  2. react-native flatlist setState修改数据视图不刷新解决方案

    给flatlist添加属性:handleMethod = {({viewableItems}) => this.handleViewableItemsChanged(viewableItems) ...

  3. TCP简单说|(上)

    本文在Creative Commons许可证下发布 TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人 ...

  4. Vijos——T 1082 丛林探险

    https://vijos.org/p/1082 描述 东非大裂谷中有一片神秘的丛林,是全世界探险家的乐园,著名黄皮肤探险家BB一直想去试试.正好我国科学家2005年4月将首次对东非大裂谷进行科考,B ...

  5. java架构解密——实时动态aop

    在上篇博客中个.咱们一起组建了一个容器,里面封装了业务,这样,咱们就将业务和服务的组装放到了client,而client就相当于咱们的开发中使用到的配置文件.大家发现问题了吗?就是我不能动态修改了?业 ...

  6. DistBelief 框架下的并行随机梯度下降法 - Downpour SGD

      本文是读完 Jeffrey Dean, Greg S. Corrado 等人的文章 Large Scale Distributed Deep Networks (2012) 后的一则读书笔记,重点 ...

  7. sdut 2805(最小生成树)

    大家快来A水题 Time Limit: 1000MS Memory limit: 65536K 题目描写叙述 (1<= N <=2000)(1<= M <= N*(N-1)/2 ...

  8. js实现删除确认提示框

    js实现删除确认提示框 一.实例描述 防止用户小心单击了“删除”按钮,在用户单击“删除”按钮后,给出一个提示,让用户确认此次操作是否正确. 二.效果 三.代码 <!DOCTYPE html> ...

  9. C#导出EXCEL(DataTable导出EXCEL)

    using System; using System.Collections.Generic; using System.Text; using System.Data; using System.I ...

  10. C# 爬虫总结

    static void Main(string[] args) { //WebRequest request = WebRequest.Create("http://www.cnblogs. ...