无法将标识列密钥生成与<union-subclass>(TABLE_PER_CLASS)一起使用


95

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的最好和最方便的方法是什么?我不想更改继承策略。

Answers:


229

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

尝试:

@GeneratedValue(strategy = GenerationType.TABLE)


2
完美的解决方案。即使是休眠论坛因此未似乎有这种解决方案,和他们绕来绕去的话题forum.hibernate.org/...
春天猴子

1
这是MySql的问题还是它的常规问题,因为我观看了针对每个类的Table方法的视频之一,并且在使用postgres时效果很好
Prashant 2014年

1
我最近在测试Dropwizard应用程序时遇到了这个问题。就我而言,我通过确保使用DW创建会话工厂所使用的相同配置选项来解决此问题。我很确定将属性“ hibernate.id.new_generator_mappings”设置为true可以解决此问题。这是DW 0.7.0,Hibernate 4.3.1,DB是H2。
Sfitts

1
完美运作。但是,强烈建议不要使用“ TABLE” ID生成策略,因为它会触发大量查询(选择,插入和更新)并维护锁以生成主键的唯一值。如果我们有一个很大的继承方案,那么对此的替代解决方案是什么?当然,它将在很大程度上影响性能。
MAC

8

我想知道这是否是特定于数据库方言的问题,因为观看了以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方言可以自己实现,或者您必须手动添加“ INHERITS”。其实我不知道。
zoidbeck

6
在PostgreSQL上,Hibernate默认使用GenerationType.SEQUENCE。这就是为什么它在那里自动运行的原因。它与PostgreSQL 绝对无关INHERITS
Henning 2014年

我一直在使用相同的教程,并且使用@Generated导致出现问题,因为我使用MySql.S花费了很多时间进行调试,直到看到这篇文章为止
Deen John

5

同意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值将自动递增并用于所有实现子类表的新记录。


2

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

因此,对我们有用的解决方案将明确使用GenerationType.SEQUENCE



0

MySQL和PostgreSQL之间存在SQL标准合规性。 PostgreSQL Postgres理解SQL92 / 99的良好子集,并为这些子集提供一些面向对象的功能。Postgres能够处理复杂的例程和规则,例如声明性SQL查询,子查询,视图,多用户支持,事务,查询优化,继承和数组。不支持跨不同数据库选择数据。

MySQL MySQL以SQL92为基础。在无数平台上运行。Mysql可以构造查询,这些查询可以联接来自不同数据库的表。同时使用ANSI和ODBC语法支持左右外部联接。从该版本的MySQL 4.1开始,MySQL将处理子查询。从版本5开始支持的视图。

有关详细说明,请访问。 http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html


请不要为此感到难过,但是我认为MySQL和PostgreSQL的比较与该主题无关(即使Hibernate的默认值与它们不同)。
mrts 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.