【问题标题】:MappedSuperclass - Change SequenceGenerator in SubclassMappedSuperclass - 在子类中更改 SequenceGenerator
【发布时间】:2023-03-22 12:26:01
【问题描述】:

我将 JPA2 与 Hibernate 一起使用,并尝试为我的实体引入一个公共基类。到目前为止,它看起来像这样:

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    private Long id;

    @Override
    public int hashCode() {
        // ...
    }

    @Override
    public boolean equals(Object obj) {
        // ...
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

但是,对于每个表,都有一个序列$entityname_seq,我想将其用作我的序列生成器。如何从我的子类中设置它?我想我需要覆盖@GeneratedValue 并使用@SequenceGenerator 创建一个新的SequenceGenerator。

【问题讨论】:

    标签: java jakarta-ee jpa sequence mappedsuperclass


    【解决方案1】:

    是的,这是可能的。您可以使用 @SequenceGenerator 注释覆盖默认生成器名称。

    • 基类
        @MappedSuperclass
        public abstract class PersistentEntity implements Serializable
        {
            private static final long serialVersionUID = 1L;
    
            @Id
            @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "default_gen")
            protected Long id = 0L;
    
            public Long getId()
            {
                return id;
            }
    
            public void setId(Long id)
            { 
                this.id = id;
            }
        }
    • 序列 (SQL)

      create sequence role_seq;
    • 派生类

        @Entity
        @Table(name = "role")
        @SequenceGenerator(name = "default_gen", sequenceName = "role_seq", allocationSize = 1)
        public class Role extends PersistentEntity implements Serializable
        {
            private static final long serialVersionUID = 1L;
    
            @NotNull
            @Size(max = 32)
            private String name;
    
            public String getName()
            {
                 return name;
            }
    
            public void setName(String name)
            {
                 this.name = name;
            }   
        }
    • 这种方法在 Hibernate 4.1.x 中运行良好,但在 EclipseLink 2.x 中却不行。

    编辑

    • 根据评论,它似乎与 EclipseLink 2.6.1-RC1 一起使用。

    【讨论】:

    • 我已经用 EclipseLink 2.6.1-RC1 进行了测试,它也可以工作。
    • 这是个好消息。谢谢!我要编辑答案。
    • 所有子类都必须定义@SequenceGenerator,否则映射会抛出错误
    • 这是一个错误的解决方案。只要您只有一个PersistentEntity 的子类,它就会起作用。假设您创建了实体“组”,它也扩展了PersistentEntity。然后你会得到错误,因为序列生成器default_gen 在同一个持久性单元中定义了两次。 (EclipseLink 2.6.2)
    • 确实如 JEE-7 所指定的“生成器名称的范围对于持久性单元是全局的(跨所有生成器类型)。”因此,即使它在某些时候适用于某些实现,它也不是标准行为。
    【解决方案2】:

    在 JPA 中无法使用注释完成。注释本身不能被覆盖。实体从MappedSuperClass 继承所有映射信息。只有两个注解可用于重新定义从映射超类继承的映射:

    1. AttributeOverride 覆盖列映射和
    2. AssociationOverride 覆盖连接列/表。

    他们都没有帮助 GeneratedValue。

    【讨论】:

      【解决方案3】:

      借助 EclipseLink,您可以使用 CustomizerDescriptorCustomizer 接口定义了一种自定义有关 jpa 描述符(又名持久实体)的所有信息的方法。

      public class SequenceCustomizer implements DescriptorCustomizer {
      
          @Override
          public void customize(ClassDescriptor descriptor) throws Exception {
              descriptor.setSequenceNumberName(descriptor.getTableName());
          }
      }
      

      在你映射的超类中:

      @MappedSuperclass
      @Customizer(SequenceCustomizer.class)
      public abstract class AbstractEntity implements Serializable {
          ...
      }
      

      【讨论】:

        【解决方案4】:

        我正在写这篇文章,因为它与已接受答案的评论一样难以理解:

        我有一个BaseEntity,其他所有实体都继承自:

        BaseEntity.java:

        @MappedSuperclass
        public abstract class BaseEntity {
        
            @Id
            @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ID")
            private Long id;
        

        然后我有两个实体UserOrder,它们都继承自BaseEntity,同时还具有@SequenceGenerator 注释:

        用户.java:

        @SequenceGenerator(name = "SEQ_ID", sequenceName = "SEQ_USER", allocationSize = 1)
        public class User extends BaseEntity { ... }
        

        Order.java:

        @SequenceGenerator(name = "SEQ_ID", sequenceName = "SEQ_ORDER", allocationSize = 1)
        public class Order extends BaseEntity { ... }
        

        它至少可以在 H2 上使用 2 个序列 SEQ_USERSEQ_ORDERS

        select SEQ_USER.nextval from dual;
        select SEQ_ORDERS.nextval from dual;
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-09
        • 1970-01-01
        • 2012-03-25
        相关资源
        最近更新 更多