4

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

  • EclipseLink 2.5.2-M1 是参考实现。
  • 休眠 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,为此我需要注释字段或属性。但它是一个休眠注释,因此它不符合 JPA2.1。
  • EclipseLink 从不生成外键约束,除非我放了 a@JoinColumn和 a foreignKeywith @ForeignKey(name="...")。但是,虽然它生成了一个外键,但缺少定义(即ALTER TABLE foobar ADD CONSTRAINT fk_foobar_zorg FOREIGN KEY () REFERENCES ():),而根据 Javadoc 它应该存在。
  • @ManyToOneHibernate 需要生成外键(抛出异常),而 EclipseLink 不需要。我不明白为什么需要它:如果引用的类型被注释了,@Entity那么我为什么要放@OneToOne, @ManyToOne@OneToMany以及@ManyToMany何时可以完美地从引用的类中推断出来。
  • EclipseLink 不会为@JoinColumn没有foreignKey集合注释的字段生成外键约束。

我应该怎么做才能以纯 JPA2.1 方式完成工作?

来源

因为我的示例案例太大而无法放在 Stackoverflow 上,所以您会找到一个包含 4 maven 3 project的存档:

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

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

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

也可以使用 Eclipse 的 Maven 插件将 POM 导入 Eclipse(在 Kepler 上测试)。

生成的 SQL

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

EclipseLink

如您所见,外键约束在语法上是无效的;并且有两个缺少的约束foobar(一个到zorg,另一个到grumph)。

    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  ()

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 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)

休眠

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

    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 grumph (id bigint not null, primary key (id))
    create table sample (id bigint not null, primary key (id))
    create table zorg (id bigint not null, primary key (id))
    alter table foobar add constraint FK_45nw30c81ae209hokgmrs9gyy foreign key (grumph_id) references grumph
    alter table foobar add constraint FK_b3pwyt79opfaopbjwaf23h11f foreign key (sample_id) references sample
    alter table foobar add constraint hb_foobar_zorg foreign key (zorg_id) references zorg
    alter table foobar_getter add constraint FK_1s2755a8mgvune6lhpfw8cifr foreign key (grumph_id) references grumph
    alter table foobar_getter add constraint FK_slbhet4s26lh9ma4vh63ltctj foreign key (sample_id) references sample
    alter table foobar_getter add constraint hb_foobar_getter_zorg foreign key (zorg_id) references zorg
4

1 回答 1

1

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

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

于 2014-01-14T21:42:15.077 回答