在项目中突然需要改一个功能,就是把原来的int类型的主键改成varchar类型,主键原来是数据库自动生成,现在要改成后台自动编号,项目使用的是springboot、mybatis,使用了通用mapper。
最开始的业务流程是,前台添加一条数据时,传递到后台的bean主键为null,然后使用insert添加数据,主键由数据库自动生成。主键改成varchar之后,需要在后台实现自动编号功能,所以流程就是前台添加一条数据,后台获得主键为null的bean,然后再给主键添加一个编号,最后调用insert方法添加数据,给主键添加编号不难,在每一个service里面添加一个add方法,在调用insert方法之前给主键一个唯一编号就可以了,但是这样不现实,应为要修改的表有很多,而且改动以前他人写的方法显然不太合理,于是想到了使用反射来写,在baseService里面写一个addAutomatic方法。代码如下:
因为主键都使用了@Id注解,所以通过判断字段是否有Id来确定是否是主键,然后根据主键是否有值来决定是否添加编号。
getTypeArguement()方法是自定义的一个方法,就是获取T这个Class对象,这个扯到泛型问题,可以先不管
public void addAutomatic(T t) {
//getTypeArguement获取泛型类型
for (Field field : getTypeArguement().getDeclaredFields()) {
//私有属性默认是不能操作的,如果想操作需要调用setAccessible开启
field.setAccessible(true);
//是否拥有指定注解类,如果没有就返回null, 有的话则返回这个注解类对象
if (field.getAnnotation(Id.class) == null)
continue;
try {
//判断这个前台有没有给主键赋值,如果没有就自动编号
if (field.get(t) != null)
continue;
//给指定的对象赋值,idSerialNumberService.getByType(getTypeArguement().getSimpleName())是自定义的自动编号(不用管、可自己实现)
field.set(t, idSerialNumberService.getByType(getTypeArguement().getSimpleName()));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//添加数据方法
add(t);
}
}
注意点: Class对象getDeclaredFields方法是获取全部(包括private)的字段,返回的是一个Filed的对象数组。