【问题标题】:Bidirectional One-To-Many-relation between two (table-per-class)-inheritance trees两个(每类表)继承树之间的双向一对多关系
【发布时间】:2013-04-24 10:54:04
【问题描述】:

摘要

说,我有两个简单的@Entity 继承树(一个抽象基类,每棵树中有两个具体实现类)InheritanceType.TABLE_PER_CLASS;我需要使用@JoinColumn 连接基类的双向@OneToMany 关系。

这应该产生 四个 表,每个具体类一个,对吧? EclipseLink 为其中一个抽象基类生成了第五个表,这对我来说没有意义。考虑这个例子(这不是一个真实的例子;它只是关于 JPA):

示例

集合是第一个继承树的抽象根和@OneToMany 关系的实现者:

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Collection {
    @Id @GeneratedValue
    public long id;
    @OneToMany(mappedBy="collection")
    public List<Media> items = new ArrayList<Media>();
}

PhysicalCollection 和 VirtualCollection 是 Collection 的具体实现:

@Entity
public class PhysicalCollection extends Collection {}

@Entity
public class VirtualCollection extends Collection {}

Media 是第二个继承树的抽象根和@ManyToOne 关系的实现者:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Media {
    @Id
    @GeneratedValue
    public long id;
    @ManyToOne
    @JoinColumn(nullable = false)
    public Collection collection;
}

CdMedia 和 TapeMedia 是 Media 的具体实现:

@Entity
public class CdMedia extends Media {}

@Entity
public class TapeMedia extends Media {}

结果

正如我所说,EclipseLink 将由此生成 五个 表(不要介意 SEQUENCE 表):

mysql> SHOW TABLES;
+--------------------+
| Tables_in_test     |
+--------------------+
| CDMEDIA            |
| MEDIA              |
| PHYSICALCOLLECTION |
| SEQUENCE           |
| TAPEMEDIA          |
| VIRTUALCOLLECTION  |
+--------------------+
6 rows in set (0.00 sec)

而且意外的表MEDIA会有一个无用的定义(重命名PhysicalCollection时外键目标改变语义):

CREATE TABLE `MEDIA` (
    `COLLECTION_ID` bigint(20) NOT NULL,
    KEY `FK_MEDIA_COLLECTION_ID` (`COLLECTION_ID`),
    CONSTRAINT `FK_MEDIA_COLLECTION_ID` FOREIGN KEY (`COLLECTION_ID`) REFERENCES PHYSICALCOLLECTION` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

问题

  1. 我的预期正确吗? (创建 4 个表,而不是 5 个)
  2. 有人可以确认这是 EclipseLink 中的错误吗?
  3. 如果不是错误,您能指出我哪里出错了吗?

【问题讨论】:

  • 我有一个类似的模型和同样的问题。你设法解决了吗?

标签: jpa eclipselink one-to-many table-per-class


【解决方案1】:

TABLE_PER_CLASS 不应该为任何抽象类创建表,所以这是一个错误。很奇怪,您还没有获得 Collection 的桌子?您确定 MEDIA 是抽象的,您是否错过了重新编译/部署代码?

我知道这个 bug 存在于 EclipseLink 2.0 中,但认为它在之后已经修复,所以你可能想尝试最新版本,否则记录一个 bug。

一般来说,我不会推荐 TABLE_PER_CLASS,尤其是在这个模型中,你有很多关系。使用 SINGLE_TABLE 或 JOINED 继承会更好。

【讨论】:

  • 是的,请放心,我多次检查过重新编译和缓存问题;)。
  • 显然,MEDIA 之所以被创建,是因为它定义了@JoinColumn(这没有任何意义),并且由于它试图引用抽象类,因此不能将底层数据库用于外键约束;因此,它错误地映射到某个具体的子类型(这几乎是犯罪的;)。
  • 与此同时,我发现还有其他人有这个问题 [verious.com/qa/jpa-one-to-many-using-inheritance/] 显然 eclipselink 目前 (v2.4.0) 不提供此功能。
  • 无论如何,如果 JPA 实现不能可靠地支持 TABLE_PER_CLASS,则应该抛出运行时异常 - 或者至少在出现问题时抛出运行时异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
相关资源
最近更新 更多