2019独角兽企业重金招聘Python工程师标准>>>

1.Mapper层参数为Map,由Service层负责重载。

Mapper由于机制的问题,不能重载,参数一般设置成Map,但这样会使参数变得模糊,如果想要使代码变得清晰,可以通过service层来实现重载的目的,对外提供的Service层是重载的,但这些重载的Service方法其实是调同一个Mapper,只不过相应的参数并不一致。

也许有人会想,为什么不在Service层也设置成Map呢?我个人是不推荐这么做的,虽然为了方便,我在之前的项目中也大量采用了这种方式,但很明显会给日后的维护工作带来麻烦。因为这么做会使你整个MVC都依赖于Map模型,这个模型其实是很不错的,方便搭框架,但存在一个问题:仅仅看方法签名,你不清楚Map中所拥有的参数个数、类型、每个参数代表的含义。

试想,你只对Service层变更,或者DAO层变更,你需要清楚整个流程中Map传递过来的参数,除非你注释或者文档良好,否则必须把每一层的代码都了解清楚,你才知道传递了哪些参数。针对于简单MVC,那倒也还好,但如果层次复杂之后,代码会变得异常复杂,而且如果我增加一个参数,需要把每一个层的注释都添加上。相对于注释,使用方法签名来保证这种代码可控性会来得更可行一些,因为注释有可能是过时的,但方法签名一般不太可能是陈旧的。

2.尽量少用if choose等语句,降低维护的难度。

Mybatis的配置SQL时,尽量少用if choose 等标签,能用SQL实现判断的尽量用SQL来判断(CASE WHEN ,DECODE等),以便后期维护。否则,一旦SQL膨胀,超级恶心,如果需要调试Mybatis中的SQL,需要去除大量的判断语句,非常麻烦。另一方面,大量的if判断,会使生成的SQL中包含大量的空格,增加网络传输的时间,也不可取。

而且大量的if choose语句,不可避免地,每次生成的SQL会不太一致,会导致ORACLE大量的硬解析,也不可取。 
我们来看看这样的SQL:

SELECT * FROM T_NEWS_TEXT WHERE 1 = 1 < choose> < if test ="startdate != null and startdate != '' and enddate != null and endate != ''"> AND PUBLISHTIME >= #{startdate} AND PUBLISHTIME <= #{enddate} </ if> <otherwise> AND PUBLISHTIME >= SYSDATE - 7 AND PUBLISHTIME <= SYSDATE </otherwise></ choose >

这样的if判断,其实是完全没有必要的,我们可以很简单的采用DECODE来解决默认值问题:

SELECT * FROM T_NEWS_TEXT WHERE PUBLISHTIME >= DECODE(#{startdate},NULL,SYSDATE-7, #{startdate}) AND PUBLISHTIME <= DECODE(#{enddate},NULL,SYSDATE,#{enddate})

当然有人会想,引入CASE WHEN,DECODE会导致需要ORACLE函数解析,会拖慢SQL执行时间,有兴趣的同学可以回去做一下测试,看看是否会有大的影响。就个人经验而言,在我的开发过程,没有发现因为函数解析导致SQL变慢的情形。影响SQL执行效率的一般情况下是JOIN、ORDER BY、DISTINCT、PARTITATION BY等这些操作,这些操作一般与表结构设计有很大的关联。相对于这些的效率影响程度,函数解析对于SQL执行速度影响应该是可以忽略不计的。

另外一点,对于一些默认值的赋值,像上面那条SQL,默认成当前日期什么的,其实可以完全提到Service层或Controller层做处理,在Mybatis中应该要少用这些判断。因为,这样的话,很难做缓存处理。如果startdate为空,在SQL上使用动态的SYSDATE,就无法确定缓存startdate日期的key应该是什么了。所以参数最好在传递至Mybatis之前都处理好,这样Mybatis层也能减少部分if choose语句,同时也方便做缓存处理。

当然不使用if choose也并不是绝对的,有时候为了优化SQL,不得不使用if来解决,比如说LIKE语句,当然一般不推荐使用LIKE,但如果存在使用的场景,尽可能在不需要使用时候去除LIKE,比如查询文章标题,以提高查询效率。 最好的方式是使用lucence等搜索引擎来解决这种全文索引的问题。

总的来说,if与choose判断分支是不可能完全去除的,但是推荐使用SQL原生的方式来解决一些动态问题,而不应该完全依赖Mybatis来完成动态分支的判断,因为判断分支过于复杂,而且难以维护。

3.用XML注释取代SQL注释。

Mybatis中原SQL的注释尽量不要保留,注释会引发一些问题,如果需要使用注释,可以在XML中用<!-- -->来注释,保证在生成的SQL中不会存在SQL注释,从而降低问题出现的可能性。这样做还有一个好处,就是在IDE中可以很清楚的区分注释与SQL。

现在来谈谈注释引发的问题,我做的一个项目中,分页组件是基于Mybatis的,它会在你写的SQL脚本外面再套一层SELECT COUNT(*) ROWNUM_ FROM (....) 计算总记录数,同时有另一个嵌套SELECT * FROM(...) WHERE ROWNUM > 10 AND RONNUM < 10 * 2这种方式生成分页信息,如果你的脚本中最后一行出现了注释,则添加的部分会成为注释的一部分,执行就会报错。除此之外,某些情况下也可能导致部分条件被忽略,如下面的情况:

SELECT * FROM TEST WHERE COL1 >  1 -- 这里是注释<if test="a != null and a != ''">AND COL2 = #{a}</if>

即使传入的参数中存在对应的参数,实际也不会产生效果,因为后面的内容实际上是被完全注释了。这种错误,如果不经过严格的测试,是很难发现的。一般情况下,XML注释完全可以替代SQL注释,因此这种行为应该可以禁止掉。

4.尽可能使用#{},而不是${}.

Mybatis中尽量不要使用${},尽量这样做很方便开发,但是有一个问题,就是大量使用会导致ORACLE的硬解析,拖慢数据库性能,运行越久,数据库性能会越差。对于一般多个字符串IN的处理,可以参考如下的解决方案:http://www.myexception.cn/sql/849573.html,基本可以解决大部分${}.

关于${},另一个误用的地方就是LIKE,我这边还有个案例:比如一些树型菜单,节点会设计成'01','0101',用两位节点来区分层级,这时候,如果需要查询01节点下所有的节点,最简单的SQL便是:SELECT * FROM TREE WHERE ID LIKE '01%',这种SQL其实无可厚非,因为它也能用到索引,所以不需要特别的处理,直接使用就行了。但如果是文章标题,则需要额外注意了:SELECT * FROM T_NEWS_TEXT WHERE TITLE LIKE '%OSC%',这是怎么也不会用到索引的,上面说了,最好采用全文检索。但如果离不开LIKE,就需要注意使用的方式: ID LIKE #{ID} || '%'而不是ID LIKE '${ID}%',减少硬解析的可能。

有人觉得使用||会增加ORACLE处理的时间,我觉得不要把ORACLE看得太傻,虽然有时候确实非常傻,有空可以再总结ORACLE傻不垃圾的地方,但是稍加测试便知:这种串联方式,对于整个SQL的解析执行,应该是微乎其微的。

当然还有一些特殊情况是没有办法处理的,比如说动态注入列名、表名等。对于这些情况,则比较棘手,没有找到比较方便的手段。由于这种情况出现的可能性会比较少,所以使用${}倒也不至于有什么太大的影响。当然你如果有代码洁癖的话,可以使用ORACLE的动态执行SQL的机制Execute immediate,这样就可以完全避免${}出现的可能性了。这样会引入比较复杂的模型,这个时候,你就需要取舍了。

针对于以上动态SQL所导致的问题,最激进的方式是全部采用存储过程,用数据库原生的方式来解决,方便开发调试,当然也会带来问题:对开发人员会有更高的要求、存储过程的管理等等,我这边项目没有采用过这种方式,这里不做更多的展开。

5.简单使用Mybatis。

Mybatis的功能相对而言还是比较弱的,缺少了好多必要的辅助库,字符串处理等等,扩展也比较困难,一般也就可能对返回值进行一些处理。因此最好仅仅把它作为单纯的SQL配置文件,以及简单的ORM框架。不要尝试在Mybatis中做过多的动态SQL,否则会导致后续的维护非常恶心。

转载于:https://my.oschina.net/zhanghaiyang/blog/725766

MyBatis学习总结(16)——Mybatis使用的几个建议相关推荐

  1. 【最全Mybatis学习笔记(导入mybatis相关jar包)】

    目录 1. 什么是Mybatis 2. 如何引入Mybatis? 3.编写Mybatis工具类 4. 万能Map 5. 模糊查询怎么写? 6. 作用域(Scope)和生命周期SqlSessionFac ...

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

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

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

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

  4. 【MyBatis学习8】MyBatis中的二级缓存

    1. 二级缓存的原理 前面介绍了,mybatis中的二级缓存是mapper级别的缓存,值得注意的是,不同的mapper都有一个二级缓存,也就是说,不同的mapper之间的二级缓存是互不影响的.为了更加 ...

  5. MyBatis学习总结(1)——MyBatis快速入门

    2019独角兽企业重金招聘Python工程师标准>>> 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所 ...

  6. 【mybatis学习记录】mybatis的各种查询 一对一关联查询(4种方式) 一对多(2种方式)

    文章目录 一对一 方式一: 方式2 方式3 方式4 一对多查询(2种方式) 方式2 一对一 如:通过订单id查询订单的时候,将订单关联的用户信息也返回. 首先建库建表: 新建实体类: @Builder ...

  7. mybatis 学习笔记:mybatis 初认识

    简介 MyBatis是一个Java持久层框架,它通过XML描述符或注解把对象与存储过程或SQL语句关联起来.mybatis 可以将 preparedStatement 中的输入参数自动进行映射,将查询 ...

  8. MyBatis学习笔记(一)——MyBatis快速入门

    转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4261895.html 一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优 ...

  9. 【MyBatis学习13】MyBatis中的二级缓存

    1. 二级缓存的原理 前面介绍了,mybatis中的二级缓存是mapper级别的缓存,值得注意的是,不同的mapper都有一个二级缓存,也就是说,不同的mapper之间的二级缓存是互不影响的.为了更加 ...

  10. MyBatis学习总结(七)——Mybatis缓存

    一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...

最新文章

  1. LaxTex---问题1: ! I can't write on file `***.pdf'.(Press Enter to retry, or Control-Z to exit; \ldots
  2. virtualC++打开汇编语言代码
  3. golang select
  4. 2020-11-6(简述html)
  5. HDMI、DVI和VGA接口互相转换问题
  6. Windows 8功能预测
  7. web前端入门教程(非常详细)
  8. 年会 炫酷 抽奖小程序
  9. 从单张图重建三维人体模型综述(一)
  10. Deepfacelab 新手教程【AI智能换脸】
  11. Tortoise SVN Clean up失败的解决方法
  12. 最小二乘估计与卡尔曼滤波公式推导
  13. mysql比赛_在Windows环境下的MySQL数据库,精彩比赛
  14. ios开发-- URL Schemes 使用详解
  15. Javascript随机生成数字字母字符串
  16. chrome浏览器当鼠标碰到超链接的时候会窗口会抖动
  17. 区块链:雷电网络开发预览版
  18. 基于LabVIEW的二维码识别程序
  19. puppy linux wifi6,Puppy官网
  20. 修改金蝶kis服务器的文件路径,金蝶kis登录修改服务器地址

热门文章

  1. img 光盘映像文件已损坏_系统封装||还在用MSDN下载Windows镜像文件?你out了,用这个就可以了...
  2. 判断有向图g中顶点i到顶点j是否有路径_号称图的最短路径算法--Floyd算法
  3. xgboost模型在centos系统下的可视化
  4. jquery input值改变事件_前端技术--JQuery
  5. python 预测算法_通过机器学习的线性回归算法预测股票走势(用Python实现)
  6. php 订单状态描述,获取不同状态订单列表
  7. 电脑开机一会就蓝屏怎么回事_常见的电脑蓝屏是怎么回事?学会三种解决方法,远离电脑维修店...
  8. 信息系统项目管理师真题及答案
  9. 备考3次终于过信息系统项目管理师长篇心路历程
  10. 2020-08-29