You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 22:36:02