java 如何在JPA中动态创建序列生成器

ykejflvf  于 2023-04-19  发布在  Java
关注(0)|答案(3)|浏览(243)

bounty将在5天后到期。回答此问题可获得+50声望奖励。user352290正在寻找来自信誉良好的来源的答案

我想通过将序列名order_sequence动态传递给这个类来重用Counter,如何实现呢

public class Counter  {
    
    @Id
    @GeneratedValue(generator = "sequence-generator")
    @GenericGenerator(name = "sequence-generator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
            @Parameter(name = "sequence_name", value = "order_sequence"),
            @Parameter(name = "initial_value", value = "1"), @Parameter(name = "increment_size", value = "1") })
    private Long counter;

}
kadbb459

kadbb4591#

主要思想可以通过以下方式覆盖org.hibernate.id.enhanced.SequenceStyleGenerator

@Target(TYPE)
@Retention(RUNTIME)
@Inherited
public @interface EntityAwareGeneratorParams {

    String sequence();

}
public class EntityAwareGenerator extends SequenceStyleGenerator {

    public static final String NAME = EntityAwareGenerator.class.getName();

    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
        String entityName = params.getProperty(ENTITY_NAME);
        if (entityName == null) {
            throw new IllegalStateException("Entity name must not be null");
        }

        Class<?> entityClass = serviceRegistry.requireService(ClassLoaderService.class)
                .classForName(entityName);

        EntityAwareGeneratorParams generatorParams = entityClass.getAnnotation(EntityAwareGeneratorParams.class);
        if (generatorParams == null) {
            throw new IllegalStateException(String.format(
                    "Annotation @%s is not present for class %s",
                    EntityAwareGeneratorParams.class.getName(),
                    entityClass.getName()
            ));
        }

        params.setProperty(SEQUENCE_PARAM, generatorParams.sequence());

        super.configure(type, params, serviceRegistry);
    }

}

MappedSuperClass:

@Id
@GeneratedValue(generator = "entity-aware-generator", strategy = GenerationType.SEQUENCE)
@GenericGenerator(name = "entity-aware-generator", strategy = EntityAwareGenerator.NAME, ...)
private Long id;

儿童班级:

@Entity
@EntityAwareGeneratorParams(sequence="another sequence")
46qrfjad

46qrfjad2#

要在JPA中动态创建序列生成器,您可以使用@GenericGenerator annotation并在运行时定义参数。请参见下面的示例:

import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;

@Entity
public class Counter {

@Id
@GeneratedValue(generator = "sequence-generator")
@GenericGenerator(name = "sequence-generator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator")
private Long counter;

public Counter() {}

public Counter(String sequenceName, int initialValue, int incrementSize) {
    GenericGenerator generator = new GenericGenerator() {
        @Override
        public String[] parameters() {
            return new String[] {
                "sequence_name=" + sequenceName,
                "initial_value=" + initialValue,
                "increment_size=" + incrementSize
            };
        }

        @Override
        public String strategy() {
            return "org.hibernate.id.enhanced.SequenceStyleGenerator";
        }
    };

    this.counter = null;
    this.sequenceGenerator = generator;
}
}

请参阅构造函数的定义,该构造函数接受序列名称,初始值和增量大小作为参数。它创建一个新的GenericGenerator对象并重写其parameters方法以返回基于输入的参数字符串数组。我们还重写其strategy方法以返回Hibernate序列生成器。然后将此生成器设置为@GenericGenerator annotation的值。
然后,您可以通过调用新的构造函数并传入所需的值来创建具有不同序列名称的Counter类的示例:

Counter orderCounter = new Counter("order_sequence", 1, 1);
Counter customerCounter = new Counter("customer_sequence", 1000, 1);
oxosxuxt

oxosxuxt3#

要在JPA中动态创建序列生成器,可以使用以下步骤:
1.定义一个自定义注解,以便对要生成动态序列的字段进行注解。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DynamicSequenceGenerator {
    String name();
}

1.更新Counter类以使用自定义注解。

public class Counter  {
    
    @Id
    @GeneratedValue(generator = "dynamic-sequence-generator")
    @DynamicSequenceGenerator(name = "order_sequence")
    private Long counter;

}

1.创建IdentifierGenerator接口的自定义实现以生成动态序列。

public class DynamicSequenceGenerator implements IdentifierGenerator {

    @Override
    public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        String sequenceName = null;

        // Get the field annotated with DynamicSequenceGenerator
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(DynamicSequenceGenerator.class)) {
                DynamicSequenceGenerator annotation = field.getAnnotation(DynamicSequenceGenerator.class);
                sequenceName = annotation.name();
                break;
            }
        }

        if (sequenceName == null) {
            throw new HibernateException("No DynamicSequenceGenerator annotation found");
        }

        // Generate the next value for the sequence
        return ((Number) session.createNativeQuery("SELECT nextval('" + sequenceName + "')").uniqueResult()).longValue();
    }
}

1.使用Hibernate注册自定义生成器。

public class HibernateConfiguration extends org.hibernate.cfg.Configuration {

    public HibernateConfiguration() {
        addAnnotatedClass(Counter.class);

        registerIdentifierGenerator("dynamic-sequence-generator", DynamicSequenceGenerator.class);
    }
}

通过这些更改,您现在可以通过使用DynamicSequenceGenerator注解来注解字段并将序列名称作为参数传递来生成动态序列。

相关问题