使用EclipseLink和Hibernate生成架构(JPA2.1) - 忽略@ForeignKey [英] Schema generation with EclipseLink and Hibernate (JPA2.1) - @ForeignKey ignored

查看:645
本文介绍了使用EclipseLink和Hibernate生成架构(JPA2.1) - 忽略@ForeignKey的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试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。

  • 除非我把 @JoinColumn foreignKey @ForeignKey(name =...)。但是,当它生成一个外键时,定义会丢失(即:> ALTER TABLE foobar ADD CONSTRAINT fk_foobar_zorg FOREIGN KEY()REFERENCES()),但它应该根据Javadoc。
  • @ManyToOne 是Hibernate生成外键(抛出异常)所必需的,但它不适用于EclipseLink 。我不明白为什么它是必需的:如果引用类型被注释为 @Entity 那么为什么要把 @OneToOne @ManyToOne @OneToMany @ManyToMany when它完全可以从引用的类推导出来。
  • EclipseLink不会为使用 @JoinColumn 注释的字段生成外键约束, code> foreignKey set。



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



来源



因为我的示例是以某种方式太大而无法放在Stackoverflow上,你会发现 with 4 maven 3项目:
$ b



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

  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



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



生成的SQL



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

EclipseLink

正如您所看到的,外键约束在语法上是无效的;并且在 foobar (一到 zorg ,另一个到 grumph )。
$ b $ pre $ CREATE TABLE foobar(ID BIGINT不为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不为NULL,PRIMARY KEY(ID))
CREATE TABLE grumph(ID BIGINT不为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()

$ b

EclipseLink(no @Table,@JoinColumn)



<没有sur奖励在这里:EclipseLink将不会被使用,如果它不能正确地产生至少的东西。

  CREATE TABLE FOOBAR(ID BIGINT不为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不为NULL,PRIMARY KEY(ID))
CREATE TABLE ZORG(ID BIGINT不为NULL,PRIMARY KEY(ID))
CREATE TABLE GRUMPH(ID BIGINT不为NULL,PRIMARY KEY(ID))
ALTER TABLE FOOBAR添加约束FK_FOOBAR_SAMPLE_ID FOREIGN KEY(SAMPLE_ID)REFERENCES SAMPLE (ID)
ALTER TABLE FOOBAR添加约束FK_FOOBAR_GRUMPH_ID FOREIGN KEY(GRUMPH_ID)引用GRUMPH(ID)
ALTER TABLE FOOBAR添加约束FK_FOOBAR_ZORG_ID FOREIGN KEY(ZORG_ID)引用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 KE Y(ZORG_ID)REFERENCES ZORG(ID)
ALTER TABLE FOOBARGETTER ADD CONSTRAINT FK_FOOBARGETTER_GRUMPH_ID FOREIGN KEY(GRUMPH_ID)REFERENCES GRUMPH(ID)

Hibernate

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

  create table foobar(id bigint not null,grumph_id bigint,sample_id bigint,zorg_id bigint,主键(id))
create table foobar_getter(id bigint not null,grumph_id bigint,sample_id bigint,zorg_id bigint,主键(id))
create table grumph(id bigint not null,主键(id))
create表格示例(id bigint不为null,主键(id))
创建表格zorg(id bigint不为null,主键(id))
表格foobar添加约束FK_45nw30c81ae209hokgmrs9gyy外键(grumph_id)引用grumph
alter table foobar add constraint FK_b3pwyt79opfaopbjwaf23h11f外键(sample_id)引用示例
alter table foobar添加约束hb_foobar_zorg外键(zorg_id)引用zorg
alter table foobar_getter添加约束FK_1s2755a8mgvune6lhpfw8cifr外键(grumph_id)引用grumph
alter table foobar_getter添加约束FK_slbhet4s26lh9ma4vh63ltctj首先ign key(sample_id)引用sample
alter table foobar_getter add constraint hb_foobar_getter_zorg外键(zorg_id)引用zorg


解决方案

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



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


I am testing JPA2.1 and the new "schema generation" feature. For that, I tested two implementations under the HyperSQL database :

  • EclipseLink 2.5.2-M1 which is the reference implementation.
  • Hibernate 4.3

I don't have any preference for an implementation (not even for performance). I tested EclipseLink because it was the first JPA2.1 implementation available, but now, Hibernate 4.3 is here and JPA2.1 compliant. The only thing I want is to get something independent from the JPA provider - except for the configuration (like cache, logging, static weaving, ...).

As for schema generation, several aspect are interesting me :

  • I'm not satisfied with the default naming strategy of EclipseLink : upper casing the entity class name, or the field/property name, make it unreadable. And I don't to extends the session customizer (I tried once and I thought it was easier, less dangerous to put annotations...).
  • I don't like Upper-case in queries; well that's a personal preference but I also had problems with mySQL on linux, because they don't follow the identifier and keywords are case insensitive unless you double-quote them SQL idiom.
  • Hibernate is, by default, not much better, but the naming strategy can be improved using ImprovedNamingStrategy. Sadly, it does not name the foreign key with an explicit name : FK_8gc2pk9u5bsbhpi91x93c77o is not explicit, while fk_foobar_sample is.

Thus, I added @Table, @JoinColumn and @Column annotation to force my naming strategy and now I'm blocked with foreign key generation, whose support seems to be pretty poor (when complying to JPA2.1) :

  • Hibernate wants me to use the @org.hibernate.annotations.ForeignKey, and for that I need to annotate the field or property. But it is an hibernate annotation, hence it is not JPA2.1 compliant.
  • EclipseLink never generate foreign key constraits, unless I put a @JoinColumn and a foreignKey with @ForeignKey(name="..."). But while it generate a foreign key, the definition is missing (ie: ALTER TABLE foobar ADD CONSTRAINT fk_foobar_zorg FOREIGN KEY () REFERENCES ()) while it should be present according to the Javadoc.
  • @ManyToOne is required for Hibernate to generate the foreign key (an exception is thrown), while it is not for EclipseLink. I don't understand why it is required : if the referenced type is annotated @Entity then why should I put @OneToOne, @ManyToOne, @OneToMany and @ManyToMany when it can perfectly be deduced from the referenced classes.
  • EclipseLink do not generate foreign key constraints for field annotated with @JoinColumn without a foreignKey set.

What should I do to the get the job done in a pure JPA2.1 way ?

Sources

Because my sample case is somehow too big to be put on Stackoverflow, you will find an archive with 4 maven 3 project :

  • jpa2.1-parent : parent project (POM)
  • jpa2.1-eclipselink : EclipseLink 2.5.2-M1 with @Table and @JoinColumn annotations.
  • jpa2.1-eclipselink-default : EclipseLink 2.5.2-M1 without @Table and @JoinColumn annotations and default naming strategy
  • jpa2.1-hibernate : Hibernate 4.3 with custom names.
  • jpa2.1-hibernate-default : Hibernate 4.3 without @Table and @JoinColumn annotations and default naming strategy

Simply run mvn test on the root project, and run whatever diff tool you like :

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

The POM can also be imported into Eclipse (tested on Kepler), using the Maven Plugin for Eclipse.

Generated SQL

For reference, here is the result of different SQL file (the drop file are wrong too, but only because the constraint name is not overloaded).

EclipseLink

As you can see, the foreign key constraints is syntaxically invalid; and there are two missing constraints on foobar (one to zorg, the other to 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 (no @Table, @JoinColumn)

No surprise here : EclipseLink would not be used if it was not able to generate something at least correct.

    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

Hibernate ignore my custom foreign key name, unless I use their annotation.

    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

解决方案

Seems I'm running into bugs of both Hibernate HHH-8783 (I will comment it again, because this does not work with @JoinTable and @OneToMany/@ManyToMany) and EclipseLink 425656, so my question is not longer relevant.

Last thing I still need to understand (but it is outside the scope of my original question) is why I have an unique key generated for @OneToMany in Hibernate, and not in EclipseLink.

这篇关于使用EclipseLink和Hibernate生成架构(JPA2.1) - 忽略@ForeignKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆