使用EclipseLink和Hibernate生成模式(JPA2.1) - @ForeignKey被忽略

时间:2014-01-14 00:02:40

标签: hibernate eclipselink java-7 jpa-2.1

我正在测试JPA2.1和新的“架构生成”功能。为此,我测试了HyperSQL数据库下的两个实现:

  • EclipseLink 2.5.2-M1,它是参考实现。
  • Hibernate 4.3

我对实现没有任何偏好(甚至没有性能)。我测试了EclipseLink,因为它是第一个可用的JPA2.1实现,但是现在,Hibernate 4.3在这里并且符合JPA2.1。我唯一想要的是从JPA提供程序中获取独立的东西 - 除了配置(如缓存,日志记录,静态编织......)。

至于模式生成,有几个方面让我感兴趣:

  • 我对EclipseLink的默认命名策略不满意:上层实体类名称或字段/属性名称使其无法读取。而且我不扩展会话定制器(我尝试了一次,我认为放置注释更容易,更危险......)。
  • 我不喜欢查询中的大写字母;这是个人偏好,但我也在linux上遇到mySQL问题,因为它们不遵循标识符,关键字不区分大小写,除非你引用它们 SQL惯用语。
  • 默认情况下,Hibernate并不是更好,但可以使用ImprovedNamingStrategy来改进命名策略。遗憾的是,它没有使用明确的名称命名外键:FK_8gc2pk9u5bsbhpi91x93c77o不明确,而fk_foobar_sample是。

因此,我添加了@Table@JoinColumn@Column注释来强制我的命名策略,现在我被外键生成阻止,其支持似乎很差(当遵守JPA2.1时):

  • Hibernate要我使用@org.hibernate.annotations.ForeignKey,为此我需要注释字段或属性。但它是一个hibernate注释,因此它不符合JPA2.1。
  • 除非我将@JoinColumnforeignKey@ForeignKey(name="...")放在一起,否则EclipseLink永远不会生成外键约束。但是当它生成一个外键时,缺少定义(即:ALTER TABLE foobar ADD CONSTRAINT fk_foobar_zorg FOREIGN KEY () REFERENCES ()),而它应该根据Javadoc存在。
  • @ManyToOne是Hibernate生成外键(抛出异常)所必需的,而不是EclipseLink。我不明白为什么需要它:如果引用的类型带有注释@Entity那么为什么我应该放@OneToOne@ManyToOne@OneToMany@ManyToMany它可以完美地从引用的类中推断出来。
  • 对于没有设置@JoinColumn的{​​{1}}注释的字段,EclipseLink不会生成外键约束。

如何以纯粹的JPA2.1方式完成工作?

来源

因为我的示例案例太大而无法放在Stackoverflow上,你会发现an archive有4个maven 3项目:

  • jpa2.1-parent:父项目(POM)
  • jpa2.1-eclipselink:带有foreignKey@Table注释的EclipseLink 2.5.2-M1。
  • jpa2.1-eclipselink-default:没有@JoinColumn@Table注释的EclipseLink 2.5.2-M1和默认命名策略
  • jpa2.1-hibernate:带有自定义名称的Hibernate 4.3。
  • jpa2.1-hibernate-default:没有@JoinColumn@Table注释的Hibernate 4.3和默认命名策略

只需在根项目上运行@JoinColumn,然后运行您喜欢的任何差异工具:

mvn test

也可以使用Maven Plugin for Eclipse将POM导入Eclipse(在Kepler上测试)。

生成的SQL

作为参考,这里是不同SQL文件的结果(drop文件也是错误的,但只是因为约束名称没有重载)。

的EclipseLink

如您所见,外键约束在语法上无效; colordiff ./jpa2.1-eclipselink/database-create.sql ./jpa2.1-hibernate/database-create.sql vimdiff ./jpa2.1-eclipselink/database-create.sql ./jpa2.1-hibernate/database-create.sql diff ./jpa2.1-eclipselink/database-create.sql ./jpa2.1-hibernate/database-create.sql kdiff3 ./jpa2.1-eclipselink/database-create.sql ./jpa2.1-hibernate/database-create.sql 上有两个缺失约束(一个到foobar,另一个到zorg

grumph

EclipseLink(没有@Table,@ JoinColumn)

这里不足为奇:如果无法生成至少正确的内容,则不会使用EclipseLink。

    CREATE TABLE foobar (ID BIGINT NOT NULL, grumph_id BIGINT, sample_id BIGINT, zorg_id BIGINT, PRIMARY KEY (ID))
    CREATE TABLE foobar_getter (ID BIGINT NOT NULL, grumph_id BIGINT, sample_id BIGINT, zorg_id BIGINT, PRIMARY KEY (ID))
    CREATE TABLE sample (ID BIGINT NOT NULL, PRIMARY KEY (ID))
    CREATE TABLE zorg (ID BIGINT NOT NULL, PRIMARY KEY (ID))
    CREATE TABLE grumph (ID BIGINT NOT NULL, PRIMARY KEY (ID))
    ALTER TABLE foobar ADD CONSTRAINT fk_foobar_zorg FOREIGN KEY () REFERENCES  ()
    ALTER TABLE foobar_getter ADD CONSTRAINT fk_foobar_getter_zorg FOREIGN KEY () REFERENCES  ()
    ALTER TABLE foobar_getter ADD CONSTRAINT fk_foobar_getter_sample FOREIGN KEY () REFERENCES  ()

休眠

Hibernate忽略我的自定义外键名称,除非我使用它们的注释。

    CREATE TABLE FOOBAR (ID BIGINT NOT NULL, GRUMPH_ID BIGINT, SAMPLE_ID BIGINT, ZORG_ID BIGINT, PRIMARY KEY (ID))
    CREATE TABLE FOOBARGETTER (ID BIGINT NOT NULL, GRUMPH_ID BIGINT, SAMPLE_ID BIGINT, ZORG_ID BIGINT, PRIMARY KEY (ID))
    CREATE TABLE SAMPLE (ID BIGINT NOT NULL, PRIMARY KEY (ID))
    CREATE TABLE ZORG (ID BIGINT NOT NULL, PRIMARY KEY (ID))
    CREATE TABLE GRUMPH (ID BIGINT NOT NULL, PRIMARY KEY (ID))
    ALTER TABLE FOOBAR ADD CONSTRAINT FK_FOOBAR_SAMPLE_ID FOREIGN KEY (SAMPLE_ID) REFERENCES SAMPLE (ID)
    ALTER TABLE FOOBAR ADD CONSTRAINT FK_FOOBAR_GRUMPH_ID FOREIGN KEY (GRUMPH_ID) REFERENCES GRUMPH (ID)
    ALTER TABLE FOOBAR ADD CONSTRAINT FK_FOOBAR_ZORG_ID FOREIGN KEY (ZORG_ID) REFERENCES ZORG (ID)
    ALTER TABLE FOOBARGETTER ADD CONSTRAINT FK_FOOBARGETTER_SAMPLE_ID FOREIGN KEY (SAMPLE_ID) REFERENCES SAMPLE (ID)
    ALTER TABLE FOOBARGETTER ADD CONSTRAINT FK_FOOBARGETTER_ZORG_ID FOREIGN KEY (ZORG_ID) REFERENCES ZORG (ID)
    ALTER TABLE FOOBARGETTER ADD CONSTRAINT FK_FOOBARGETTER_GRUMPH_ID FOREIGN KEY (GRUMPH_ID) REFERENCES GRUMPH (ID)

1 个答案:

答案 0 :(得分:1)

似乎我遇到了两个Hibernate HHH-8783的错误(我会再次发表评论,因为这不适用于@JoinTable@OneToMany / @ManyToMany)和EclipseLink 425656,所以我的问题不再相关。

我还需要了解的最后一件事(但它超出了原始问题的范围)是为什么我在Hibernate中为@OneToMany生成了一个唯一的密钥,而不是在EclipseLink中。