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 = 1and publishtime >= #{startdate} and publishtime = sysdate - 7 and publishtime = decode(#{startdate},null,sysdate-7, #{startdate}) and publishtime 10 and ronnum 1 -- 这里是注释and col2 = #{a}
即使传入的参数中存在对应的参数,实际也不会产生效果,因为后面的内容实际上是被完全注释了。这种错误,如果不经过严格的测试,是很难发现的。一般情况下,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,否则会导致后续的维护非常恶心。
