Mybatis在工程中的槽点
工程中的mapper文件往往非常大,动则上千行,最近经常听见周围的同学们吐槽难以维护,还不如写Java代码。
最近就在思考这样一个问题,既然mapper文件太那蛋疼,为什么大家还是使用mapper文件呢,为什么不使用mybatis的注解或者使用spring-jdbc提供的JdbcTemplate(有使用JPA的)
结合自己的思考和一些实验,觉得有以下原因:
- 有些同学被一些视频洗脑了,认为xml比java代码更好维护
- Java中写sql实在不是一个好的sql编写方式,用java写出来的sql确实比xml中的sql更难看懂
- 虽然mybatis提供了注解的方式,但是sql还是非常难以编写
- ResultMap还是得用xml,否则就得重复的写多次@Results
总结起来其实就一个原因:Java的语法对长一点的字符串太不友好了,很难编写出可读性好的SQL,所以大家还是更愿意写xml来表示sql的对象的映射
不使用xml的方式
如何做到不使用xml呢?其实是有多种选择的,比如mybatis for scala,但是scala语法不熟悉,学习成本太大,实际上如果Java对string有比较好的支持,那写sql会容易得多
虽然Java对String的支持不够友好,但是groovy或者kotlin对string有非常好的支持,可以尝试用groovy或者kotlin加上mybatis的注解来写映射接口,比如kotlin:
因为Java是可以和groovy或者kotlin在同一工程中混合使用的,因此使用kotlin或者groovy的方式在Java中是能正常被调用的,有了这种语法糖层面的支持,在代码中写SQL变得容易很多
解决重复SQL的问题
使用注解后,如果需要写多个查询,查询字段需要写多次,例如(本例中省略了ResultMap的使用):
这里的select之后的字段名,在多个不同的查询之中都是相同的,如何解决这个问题呢?我们可以使用mybatis插件处理,最后的效果如下:
关键在于处理这个@Macro注解,
注解定义如下:
插件中需要处理sql,对sql做文本替换,这样我们就能够得到通过注解支持的可利用的sql片断,插件实现如下:
对ResultMap的处理
在前面的例子中,映射接口中省略了@Results,加上@Results后完整的注解使用方式应该如下:
可以看到,需要在每个查询方法上都加上@Results,如果多个方法上的@Result一模一样,那么重复的注解会被定义多次。
同样,我们可以通过实现mybatis插件方式支持默认的ResultMap,最终效果如下:
如果数据库中的字段名与Java中的属性名是标准的下划线与驼峰格式,比如数据库中的create_time对应于java中的createTime,那么可以不写@DefaultResults的results属性,例如:
整体代码简洁很多,使用多行字符串语法后如下:
未完待续
今天太晚了,后面再继续讲述如何简化动态sql在mapper接口中的编写