如何为JPARepository的ID生成器在运行时添加动态前缀替代静态方案
解决方案
1 修改自定义IdGenerator实现类
核心调整为从当前待保存的实体对象中读取dept属性作为动态前缀,同时优化ID最大值查询逻辑,按部门前缀过滤避免跨部门序号冲突:
public class IdGenerator implements IdentifierGenerator, Configurable { // 保留默认前缀作为dept为空时的兜底 private String defaultPrefix; @Override public Serializable generate(SharedSessionContractImplementor session, Object obj) throws HibernateException { // 从当前实体对象提取dept作为动态前缀 UserModel user = (UserModel) obj; String dynamicPrefix = user.getDept(); // 空值兜底 if (dynamicPrefix == null || dynamicPrefix.isBlank()) { dynamicPrefix = defaultPrefix; } String idFieldName = session.getEntityPersister(obj.getClass().getName(), obj).getIdentifierPropertyName(); String queryStr = String.format("select %s from %s where %s like :prefix", idFieldName, obj.getClass().getSimpleName(), idFieldName ); // 仅查询当前部门前缀的ID,避免不同部门序号冲突 Stream<String> ids = session.createQuery(queryStr, String.class) .setParameter("prefix", dynamicPrefix + "-%") .stream(); Long max = ids.map(o -> o.replace(dynamicPrefix + "-", "")) .mapToLong(Long::parseLong) .max() .orElse(0L); return dynamicPrefix + "-" + (max + 1); } @Override public void configure(Type type, Properties properties, ServiceRegistry serviceRegistry) throws MappingException { // 读取配置的前缀作为默认兜底值 defaultPrefix = properties.getProperty("prefix", "DEPT"); } }
2 调整UserModel的生成器配置
保留原有配置即可,配置的prefix值会作为dept字段为空时的默认兜底前缀,如果不需要兜底也可以删除parameters配置项:
@Id @GeneratedValue(generator = "prod-generator") @GenericGenerator(name = "prod-generator", parameters = @Parameter(name = "prefix", value = "DEPT"), strategy = "com.otomate.registerservice.service.IdGenerator") private String id;
可选优化(多实体兼容)
如果该ID生成器需要供多个带dept属性的实体共用,可以将强转UserModel的逻辑替换为反射读取字段,适配所有包含dept属性的实体:
// 替换原来的强转逻辑 String dynamicPrefix = null; try { Field deptField = obj.getClass().getDeclaredField("dept"); deptField.setAccessible(true); dynamicPrefix = (String) deptField.get(obj); } catch (NoSuchFieldException | IllegalAccessException e) { // 读取失败时用默认前缀 dynamicPrefix = defaultPrefix; }
效果验证
按你提供的输入示例,dept值为SALES时,会自动查询所有SALES-%格式的ID取最大值+1,最终生成SALES-1,符合预期。
内容的提问来源于stack exchange,提问作者Dhamodaran N
相关产品推荐
相关产品推荐

