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. vuex 快速入门( 基于vue2.0,vue1.0未知可否)

    1.原理概述 2.用户登录例子解析: 由上图可以看到: 1.组件的数据是username,我们把它以name放在state中: 2.更改name发生在mutations的回调里,事件名字是showUs ...

  2. 进阶《Python高性能编程》中文PDF+英文PDF+源代码

    入门使用高性能 Python,建议参考<Python高性能编程>,例子给的很多,讲到高性能就会提到性能监控,里面有cpu mem 方法的度量,网络讲了一点异步,net profiler 没 ...

  3. 关于getinstalledpackages參数的分析。

    此blog不写API的使用方法仅仅分析此參数的知识点. 今天学习安卓突然学习到了getinstalledpackages()的方法获取到安装应用信息 ,他接收一个int flags的值.然后在网上查询 ...

  4. opencms9.0安装

    今天安装opencms 9.0遇到了一些问题,因为是初次安装和使用,导致耽误了非常多时间.所以在此记录一下以备以后借鉴. 首先附上安装步骤链接: http://www.51testing.com/ht ...

  5. sublime 支持 vue 语法

    具体步骤如下: 1.如果你没安装Package Control,请先安装,安装方法请自行百度.安装OK后,接下来步骤请参考第2步即可. 2.如果你已经安装过Package Control,安装vue高 ...

  6. VisualRoute for Mac OS 体验

    VisualRoute 网络路径结点回溯分析工具,以在世界地图上显示连结的路径的方式,让你知道当无法连上某些IP时的真正问题所在.VisualRoute将traceroute.ping以及Whois等 ...

  7. 分享一下10个常用jquery片段

      1. 图片预加载 (function($) { var cache = []; // Arguments are image paths relative to the current page. ...

  8. sql server 怎样用select语句调用自定义表值函数

    --自定义函数的参数是表的字段,这种情况要用cross apply啦Select B.* FROM [master].[dbo].[分列测试] A cross apply dbo.f_split(应用 ...

  9. hbase xshell

    用Xshell登陆linux主机后,在hbase shell下死活不能使用backspace和delete删除误输的指令,只得不停退出,重登,仔细输..又错了,再退出,再登,仔细输...又错了...又 ...

  10. PS:切图

    1.从psd中获取资源 2.基本了解 3.简单的图片操作和调整 4.对自己的审美提高一.界面设置: 1.新建设置:ctr+n; 预设:Web,大小Web(1920*1080) 背景:透明 2.移动工具 ...