在子类的Hibernate中为每个表指定不同的序列

gut*_*tch 23 java postgresql hibernate sequence

有没有办法为Hibernate中的每个表指定不同的序列,如果ID是在映射的超类上定义的?

我们的应用程序中的所有实体都扩展了一个名为的超类DataObject:

@MappedSuperclass
public abstract class DataObject implements Serializable {
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id")
    private int id;
}

@Entity
@Table(name = "entity_a")
public class EntityA extends DataObject { ... }

@Entity
@Table(name = "entity_b")
public class EntityB extends DataObject { ... }
Run Code Online (Sandbox Code Playgroud)

这会导致所有实体使用默认的共享序列hibernate_sequence.

我希望做的是使用一个单独的序列为每个实体,例如entity_a_sequenceentity_b_sequence上面的例子.如果在子类上指定了ID,那么我可以使用@SequenceGenerator注释为每个实体指定序列,但在这种情况下,ID在超类上.鉴于ID在超类中,是否有一种方法可以为每个实体使用单独的序列 - 如果是,那么如何?

(我们正在使用PostgreSQL 8.3,如果相关的话)

小智 36

你试过这样做吗?

@MappedSuperclass
public abstract class DataObject implements Serializable {
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idgen")
    @Column(name = "id")
    private int id;
}

@Entity
@SequenceGenerator(initialValue = 1, name = "idgen", sequenceName = "entityaseq")
@Table(name = "entity_a")
public class EntityA extends DataObject { 

}

@Entity
@SequenceGenerator(initialValue = 1, name = "idgen", sequenceName = "entitybseq")
@Table(name = "entity_b")
public class EntityB extends DataObject {

}
Run Code Online (Sandbox Code Playgroud)

对不起,我现在没有必要的环境来测试它,但我会稍后再试.

  • 是的——它确实有效!我尝试过类似的方法,但不断收到“org.hibernate.AnnotationException:未知的 Id.generator:idgen”。然而你的代码运行良好;事实证明,我在第一次尝试时忘记在其中一个子类中包含“@SequenceGenerator”。所以答案是它确实有效,只要每个实体子类都有 @SequenceGenerator 注解即可。 (2认同)
  • 这适用于版本<5.2.14和> = 5.2.17.请参阅https://hibernate.atlassian.net/browse/HHH-12329,http://in.relation.to/2018/04/26/hibernate-orm-5217-final-release/ (2认同)

Fra*_*ans 7

我们在所有JPA实体的抽象超类中使用此方法:

@Id
@GeneratedValue(generator = "pooled")
@GenericGenerator(name = "pooled", strategy = "org.hibernate.id.enhanced.TableGenerator", parameters = {
        @org.hibernate.annotations.Parameter(name = "value_column_name", value = "sequence_next_hi_value"),
        @org.hibernate.annotations.Parameter(name = "prefer_entity_table_as_segment_value", value = "true"),
        @org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled-lo"),
        @org.hibernate.annotations.Parameter(name = "increment_size", value = "100")})
private Long id;
Run Code Online (Sandbox Code Playgroud)

这有点冗长,但是它允许设置,prefer_entity_table_as_segment_value这意味着您不需要id在子类中重复字段或生成器注释。


Jen*_*gsa 7

I was not quite happy about the need to declare the sequence name on each class individually. I have checked the source code and came up with this solution:

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import org.hibernate.id.enhanced.SequenceStyleGenerator;

// ...

@Id
@GeneratedValue(generator = "sequenceIdGenerator")
@GenericGenerator(
        name = "sequenceIdGenerator", 
        strategy = "sequence",
        parameters = @Parameter(
                name = SequenceStyleGenerator.CONFIG_PREFER_SEQUENCE_PER_ENTITY,
                value = "true"))
@Column(updatable = false, nullable = false)
protected Long id;
Run Code Online (Sandbox Code Playgroud)