主键生成策略
基于多租户生成方式
首先需要对当前的id进行拦截操作,也即使用aop的切面Aspect对切点进行拦截,在进行新增的时候进行拦截:
@Pointcut("execution(* com.xtt..*.dao.mapper..*.insert*(..))")
public void primaryKeyRule() {}
也就是说在进行主键的生成时,我们拦截好需要生成的主键,此时就可以对其进行新增操作了,而首要的就是拿到它的primaryKey。由于进行新增操作,通常分为两种情况:
批量插入
单条插入
因此在通过切点JoinPoint拿到参数,通过实例化来判断当前的实体是列表还是单个操作,如果是单个走单个操作,如果是批量走批量操作:
public void doBefore(JoinPoint jp) {
Object entity = jp.getArgs()[0];
if (entity instanceof List) {
setPrimaryKeyBatch((List<Object>)entity);
} else {
setPrimaryKey(entity, entity.getClass());
}
}
此时通过反射拿到声明方法中的字段,下面针对单个新增进行说明:
通过字节码拿到声明的方法getId,如果此时存在id,则说明此时的操作是更新操作,因此直接返回。如果当前通过字节码拿到的声明方法getTenant,通过租户方法拿到租户id。拿到租户id后,就可以进行主键id获取了。
private void setPrimaryKey(Object entity, Class<? extends Object> clazz) {
Long id = (Long)clazz.getDeclaredMethod("getId").invoke(entity);
Integer tenantId;
Method tenantGet = clazz.getDeclaredMethod("getTenant");
tenantId = (Integer)tenantGet.invoke(entity);
//省略异常处理...
// 获取类名称、租户id、需要新增的个数1
id = PrimaryKeyUtils.getPrimaryKey(clazz.getSimpleName(), tenantId, 1);
// 然后通过setId 计数进行invoke
clazz.getDeclaredMethod(METHOD_SET_ID, Long.class).invoke(entity, id);
// 省略异常处理...
}
获取主键id:
public static synchronized Long getPrimaryKey(String modelName, Integer tenantId, int count) {
String id = (tenantId == null ? SystemConstant.DEFAULT_SYS_TENANT_ID : tenantId) + modelName;
Long current = (Long)DBUtils.getSingle("select getPrimaryKeyWithCount('" + id + "'," + count + ") from dual;");
current = current - count + 1;
// 省略异常处理...
return current;
}
从而实现主键自增的目的,从而实现基于租户id进行自增的策略。