1.主键生成策略方式
主键生成策略
2.基于Saas主键表生成主键id流程
由于我们的系统时基于Saas的,因此生成主键时,需要以租户id(TenantId)为基础进行生成。为了生成的id符合我们的租户的要求,通常都会现将租户表建好,然后基于租户表中的租户id进行主键id的生成。此时便产生基于租户id生成主键,那么怎样生成主键id呢?可以查看下图:
基于多租户生成方式
3.主键id生成实现的具体方式
首先需要对当前的id进行拦截操作,也即使用aop的切面Aspect对切点进行拦截,在进行新增的时候进行拦截:
@Pointcut("execution(* com.xtt..*.dao.mapper..*.insert*(..))") public void primaryKeyRule() {}
也就是说在进行主键的生成时,我们拦截好需要生成的主键,此时就可以对其进行新增操作了,而首要的就是拿到它的primaryKey。由于进行新增操作,通常分为两种情况:
批量插入单条插入
因此在通过切点JoinPoint拿到参数,通过实例化来判断当前的实体是列表还是单个操作,如果是单个走单个操作,如果是批量走批量操作:
publicvoiddoBefore(JoinPointjp) { Objectentity=jp.getArgs()[0]; if (entityinstanceofList) { setPrimaryKeyBatch((List<Object>)entity); } else { setPrimaryKey(entity, entity.getClass()); } }
此时通过反射拿到声明方法中的字段,下面针对单个新增进行说明:
通过字节码拿到声明的方法getId,如果此时存在id,则说明此时的操作是更新操作,因此直接返回。如果当前通过字节码拿到的声明方法getTenant,通过租户方法拿到租户id。拿到租户id后,就可以进行主键id获取了。
privatevoidsetPrimaryKey(Objectentity, Class<?extendsObject>clazz) { Longid= (Long)clazz.getDeclaredMethod("getId").invoke(entity); IntegertenantId; MethodtenantGet=clazz.getDeclaredMethod("getTenant"); tenantId= (Integer)tenantGet.invoke(entity); //省略异常处理...// 获取类名称、租户id、需要新增的个数1id=PrimaryKeyUtils.getPrimaryKey(clazz.getSimpleName(), tenantId, 1); // 然后通过setId 计数进行invokeclazz.getDeclaredMethod(METHOD_SET_ID, Long.class).invoke(entity, id); // 省略异常处理...}
获取主键id:
publicstaticsynchronizedLonggetPrimaryKey(StringmodelName, IntegertenantId, intcount) { Stringid= (tenantId==null?SystemConstant.DEFAULT_SYS_TENANT_ID : tenantId) +modelName; Longcurrent= (Long)DBUtils.getSingle("select getPrimaryKeyWithCount('"+id+"',"+count+") from dual;"); current=current-count+1; // 省略异常处理...returncurrent; }
从而实现主键自增的目的,从而实现基于租户id进行自增的策略。