【问题标题】:Cannot use identity column key generation with <union-subclass> ( TABLE_PER_CLASS )不能通过 <union-subclass> ( TABLE_PER_CLASS ) 使用标识列键生成
【发布时间】:2010-10-29 07:21:10
【问题描述】:

com.something.SuperClass:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuperClass implements Serializable {
    private static final long serialVersionUID = -695503064509648117L;

    long confirmationCode;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) // Causes exception!!!
    public long getConfirmationCode() {
        return confirmationCode;
    }

    public void setConfirmationCode(long confirmationCode) {
        this.confirmationCode = confirmationCode;
    }
}

com.something.SubClass:

@Entity
public abstract class Subclass extends SuperClass {
    private static final long serialVersionUID = 8623159397061057722L;

    String name;

    @Column(nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

给我这个例外:

Caused by: org.hibernate.MappingException: Cannot use identity column key
generation with <union-subclass> mapping for: com.something.SuperClass

生成 ID 的最佳和最方便的方法是什么? 我不想改变我的继承策略。

【问题讨论】:

    标签: hibernate inheritance jpa class-table-inheritance


    【解决方案1】:

    这里的问题是你混合了“每类表”继承和GenerationType.Auto。 考虑 MsSQL 中的标识列。它是基于列的。在“每类表”策略中,每个类使用一个表,每个表都有一个 ID。

    试试:

    @GeneratedValue(strategy = GenerationType.TABLE)

    【讨论】:

    • 完美解决方案。甚至 Hibernate 论坛似乎也没有这个解决方案,他们围绕着这个话题 forum.hibernate.org/…
    • 这个问题是只存在于 MySql 还是它的常规问题,因为我观看了每个班级方法的 Table 视频之一,并且在使用 postgres 时它工作正常
    • 我最近在测试 Dropwizard 应用程序时遇到了这个问题。在我的例子中,我通过确保使用与 DW 相同的配置选项来创建会话工厂来解决这个问题。我很确定将属性“hibernate.id.new_generator_mappings”设置为 true 是修复它的原因。这是 DW 0.7.0,Hibernate 4.3.1,DB 是 H2。
    • 完美运行。但是,强烈建议不要更喜欢使用 'TABLE' id 生成策略,因为它会触发大量查询(选择、插入和更新)并维护锁以生成主键的唯一值。那么如果我们有一个很大的继承场景,那么有什么替代解决方案呢?它肯定会在很大程度上影响性能。
    【解决方案2】:

    我想知道这是否是特定于数据库方言的问题,因为观看了一个使用 PostgreSQL 作为底层数据库的 youtube 教程,我看到视频的创建者成功地运行了一个具有默认 @GeneratedValue 的应用程序。就我而言(底层数据库是 MySQL),我必须完全按照 zoidbeck 的建议将 @GeneratedValue 策略修改为 GenerationType.TABLE。

    这是视频:https://www.youtube.com/watch?v=qIdM4KQOtH8

    【讨论】:

    • Postgres 能够进行继承,因此您可能是正确的,这是特定于数据库的:postgresql.org/docs/8.1/static/ddl-inherit.html 该视频没有解释(或者我错过了)模式是如何生成的。因此,也许 NHibernate postgres 方言可以自己完成,或者您必须手动添加“继承”。其实我说不出来。
    • 在 PostgreSQL 上,Hibernate 默认使用GenerationType.SEQUENCE。这就是它在那里自动工作的原因。它与 PostgreSQLs INHERITS 完全没有任何关系
    • 我一直在使用相同的教程和使用@Generated 导致问题,因为我正在使用 MySql。花了很多时间调试,直到我看到这篇文章
    【解决方案3】:

    同意 zoidbeck 的回答。 您需要将策略更改为:

    @GeneratedValue(strategy = GenerationType.TABLE)
    

    但这还不是全部,您需要创建一个新表,它将保存您摘要的表主键序列。将您的映射修改为

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "ConfirmationCodeGenerator")
    @TableGenerator(table = "SEQUENCES", name = "ConfirmationCodeGenerator")
    public long getConfirmationCode() {
       return confirmationCode;
    }
    

    数据库中的新表应如下所示:

    当您运行应用程序时,Hibernate 将插入一行,其中sequence_name 将是实体名称(在此示例中为SuperClass),sequence_next_hi_value 值将自动递增并用于所有实现子类表的新记录.

    【讨论】:

      【解决方案4】:

      您可以使用@MappedSuperclass 进行继承

      【讨论】:

        【解决方案5】:

        在我们的例子中,我们使用 PostreSQL 数据库进行开发和生产,使用内存中的 hsqldb 数据库进行测试。在这两种情况下,我们都使用序列来生成 id。显然 GenerationType.AUTO 对于 postgres 默认为 SEQUENCE,但在我们的本地测试中失败(对于 hsqldb 必须默认为其他值)。

        所以对我们有用的解决方案,明确使用GenerationType.SEQUENCE

        【讨论】:

          猜你喜欢
          • 2014-01-29
          • 1970-01-01
          • 2013-08-07
          • 1970-01-01
          • 2010-12-16
          • 2020-04-03
          • 1970-01-01
          • 2012-02-26
          • 2011-10-01
          相关资源
          最近更新 更多