不能使用<union-subclass>(TABLE_PER_CLASS)</union-subclass>生成标识列密钥

时间:2009-05-27 14:49:01

标签: hibernate inheritance jpa class-table-inheritance

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

6 个答案:

答案 0 :(得分:206)

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

尝试:

@GeneratedValue(strategy = GenerationType.TABLE)

答案 1 :(得分:8)

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

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

答案 2 :(得分:2)

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

因此,适用于我们的解决方案明确使用GenerationType.SEQUENCE

答案 3 :(得分:2)

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

@GeneratedValue(strategy = GenerationType.TABLE)

但这不是全部,你需要创建一个新表,什么将保存你的抽象表主键序列。将映射修改为

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

数据库中的新表应如下所示: enter image description here

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

答案 4 :(得分:1)

您可以使用@MappedSuperclass进行继承

答案 5 :(得分: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