我正在测试 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
is.
因此,我添加了@Table
, @JoinColumn
and @Column
强制注释我的命名策略现在我被外键生成阻止了,它的支持似乎很差(当遵守 JPA2.1 时):
- Hibernate 希望我使用
@org.hibernate.annotations.ForeignKey
,为此我需要注释该字段或属性。但它是一个 hibernate 注释,因此它不符合 JPA2.1。
- EclipseLink 永远不会生成外键约束,除非我放置一个
@JoinColumn
and a foreignKey
with @ForeignKey(name="...")
。但是,当它生成外键时,缺少定义(即:ALTER TABLE foobar ADD CONSTRAINT fk_foobar_zorg FOREIGN KEY () REFERENCES ()
),而根据 Javadoc 它应该存在。
-
@ManyToOne
Hibernate 需要生成外键(会抛出异常),而 EclipseLink 则不需要。我不明白为什么需要它:如果引用的类型被注释@Entity
那我为什么要放@OneToOne
, @ManyToOne
, @OneToMany
and @ManyToMany
当它可以从引用的类中完美推导出来时。
- EclipseLink 不会为注释的字段生成外键约束
@JoinColumn
没有foreignKey
set.
我应该怎么做才能以纯粹的 JPA2.1 方式完成工作?
Sources
因为我的示例案例太大而无法放在 Stackoverflow 上,你会发现档案有 4 个 Maven 3 项目:
- jpa2.1-parent :父项目(POM)
- jpa2.1-eclipselink :EclipseLink 2.5.2-M1 与
@Table
and @JoinColumn
注释。
- jpa2.1-eclipselink-default :EclipseLink 2.5.2-M1 不带
@Table
and @JoinColumn
注释和默认命名策略
- jpa2.1-hibernate :具有自定义名称的 Hibernate 4.3。
- jpa2.1-hibernate-default :Hibernate 4.3 不带
@Table
and @JoinColumn
注释和默认命名策略
只需运行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
还可以使用 Eclipse 的 Maven 插件将 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 无法生成某些内容,则不会使用它at least正确的。
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