Sonar烦恼
今天把一个业务项目上传到了SonarQube,提示代码重复率7.5%,默认的标准是5%,超标了。
本来因为只是个用作数据收集的新项目,使用到的表比较少,而表的基本字段有重复,使用了Spring-boot-data-jpa生成的model对象属性便有部分重复。
本来是个小事情,置之不理就好,但是。。。
尝试使用extends对model进行继承结构梳理,A extends B,尝试编译,报错:【子类builder不能覆盖父类】。因为在model上使用了lombok的builder注解,创建的builder方法不能覆盖。
由于builder结构的便利性,在业务代码中多次使用了类似A.builder().aaa().bbb().build()这种写法,不忍舍弃,尝试google解决,得到@SuperBuilder注解,在最新的lombok18上有提供,赶紧更改依赖包版本,更改注解测试,按文档说明父类子类都使用@SuperBuilder标注,测试方法中尝试B.builder(),未能获得。使用compile编译,观察生成class文件,的确已经存在使用了泛型并且支持继承关系的builder对象和builder()方法,为什么不成功呢?
猜测是lombok插件的问题,打开idea的插件管理器,查看lombok plugin支持注解列表说明,果然没有@SuperBuilder,看来只支持到1.16的lombok版本。尝试双击lombok.jar安装插件,发现只支持eclipse核心ide,想让我换开发工具?不存在的~ 算了放弃放弃。
尝试@Accessors注解,加上chain=true之后,生成的setter方法会将自身返回,看起来很好用,然而子类的示例,调用了父类属性的setter之后,返回的对象就变成父类了,需要声明下类型转换,略麻烦。
还是回到@Builder注解做文章,观察注解属性列表,发现builder方法名、类名、build方法名,都是可以更改的!尝试加上(builderMethodName = "aesbuilder")进行编译,通过了!观察生成的builder方法,已然变成了aesbuilder(),very Good。
然而,同时也发现了一个严重问题,builder返回的Builder类,支持的属性设置,只有子类的,而继承自父类的属性并不在里面。而事实上,@SuperBuilder正是用来解决这一问题的,然而并没有可用的idea插件。。。
google发现了一个大神给的方案,@Builder声明在构造方法上,而构造方法参数里,把需要用到的属性逐个声明一遍,虽然略笨重,不过看似可行,于是改造代码为
@Builder(builderMethodName = "aesbuilder")
public ActivityEventStatistic(final Long id, final String pageCode, final String eventCode, final Integer pv, final Integer uv, final Integer timeHour,final String activityCode){
super(id, pageCode, eventCode, pv, uv, timeHour);
this.activityCode = activityCode;
}
public static void main(String[] args) {
ActivityEventStatistic.aesbuilder().id(123l).pageCode("test").build();
}
it works! wow~
OK,编译通过,进入测试阶段,test case跑起来,然后duang~ 又遇到问题了!提示执行的查询sql,属性未找到。分析之后发现,由于model使用了继承,而没有显示声明Inheritance策略,所以jpa使用了默认的策略SINGLE_TABLE,也就是父类子类公用了一张表,再加上并没有声明哪些属性属于子类,所以就报错了。
另外,很显然,我这种情况并不能使用SINGLE_TABLE,而应该使用TABLE_PER_CLASS。ok,在model上加上@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS),再次run test,报错如下:
nested exception is org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: com.quzeng.idss.domain.PageStatistic
查找问题后得知,在model上使用了继承关系后,就不能使用自动主键策略了,而只能用GenerationType.TABLE才可以。。。吐血。。。
ok,创建表hibernate_sequences,添加字段sequence_name,next_val,尝试run test,总算成功了。。。
但是,面临的问题还是有的,首当其冲的是,GenerationType.TABLE被人诟病因为每次请求时的锁机制造成的性能严重影响的问题,参考:why-you-should-never-use-the-table-identifier-generator-with-jpa-and-hibernate,另外一个,是我要对每个表创建ID生成器,指定序列器名称、范围,以及hibernate_sequences 表中要添加好相应记录,还要将这些改动脚本整理下来,告知DBA,说是因为一个蛋疼的重复率指标导致的主键策略改动,还不知道会不会被拒绝掉。。。
哎,你说我瞎折腾什么呢。👀
网友评论