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

标签 hibernate eclipselink java-7 jpa-2.1

我正在测试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永远不会生成外键约束,除非我在@JoinColumnforeignKey之间加上@ForeignKey(name="...")。但是,虽然它生成外键,但缺少定义(即:ALTER TABLE foobar ADD CONSTRAINT fk_foobar_zorg FOREIGN KEY () REFERENCES ()),而根据Javadoc应该存在该定义。
Hibernate需要@ManyToOne来生成外键(引发异常),而EclipseLink则不需要。我不明白为什么要这样做:如果引用的类型是带注释的@Entity,那么当可以从引用的类中完美推断出@OneToOne@ManyToOne@OneToMany@ManyToMany时,为什么还要放它呢?
EclipseLink不会为未设置@JoinColumn的带有foreignKey注释的字段生成外键约束。


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

资料来源

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


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


只需在根项目上运行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(在Kepler上测试)。

生成的SQL

作为参考,这是不同的SQL文件的结果(丢弃文件也是错误的,但仅是因为约束名称未超载)。

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

最佳答案

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

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

关于hibernate - 使用EclipseLink和Hibernate(JPA2.1)生成模式-忽略@ForeignKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21103795/

相关文章:

hibernate - Spring Data 悲观锁超时与 Postgres

java - 将新的 transient 字段添加到现有的@Enity

java - 在 JPA (EclipseLink) 中有一个类似 @Formula 的注释来设置来自子查询的计算字段?

java - 悲观锁不起作用

java - Apaches Ignite 不会序列化/反序列化 Guavas LoadingCache

java - 通过执行一个简单的 Spring Hibernate 集成程序,我遇到了以下问题

java - Hibernate 堆栈溢出错误

java - JPA查询优化

java - 我如何使用 JDK 1.7 运行 jersey 2.26?

如果尝试使用反射将值设置为 String 类的 value[] 字段,Java 6 和 Java 7 会产生不同的结果