Hibernate无法找到正确的外键

时间:2013-10-23 09:28:15

标签: java hibernate junit hsqldb

我遇到一个问题,即hibernate试图删除不存在的外键而不是存在的外键。我的场景看起来像这样。

我想运行junit测试,在测试之前我想要创建数据库,并且在测试之后我想删除它。为此我使用了hibernate create-drop属性。然而,棘手的部分是我想创建自己的表作为测试新添加的sql的一种方法,并验证一旦我将它部署到生产数据库服务器就可以正常运行。那么会发生什么呢

  • Hibernate自动创建表格
  • Hibernate创建外键关系
  • Hibernate运行我的drop table脚本(由于没有数据,所以没有成功,因此没有破坏外键规则)
  • Hibernate运行我的创建表脚本
  • Hibernate运行我的添加外部约束脚本
  • Hibernate运行我的插入数据脚本
  • 执行测试
  • Hibernate尝试删除外键,但失败了。

hibernate无法删除它的原因是它试图删除那个hibernate创建的那个而不是我的脚本创建的那个。

知道如何强制hibernate找出实际的外键吗?有什么方法可以解决这个问题吗?

谢谢大家

hibernate为其创建表的类

TodoGroup.java

@Entity
@Table(name = "ToDoGroups")
public class ToDoGroup implements Serializable{


    @Id
    @GeneratedValue
    private Long id;
    @Column(name = "Name", length = 50)
    private String name;
    @ManyToOne
    @JoinColumn(name = "UserSettingsId")
    @XmlTransient
    private UserSettings userSettings;
    @OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
    private List<ToDoItem> items;

hibernate添加约束

alter table ToDoGroups 
        add constraint FK790BA1FAFE315596 
        foreign key (UserSettingsId) 
        references UserSettings

运行我自己的表,因为没有数据所以工作正常,所以我可以删除为了验证我的sql而创建的hibernate

DROP TABLE IF EXISTS ToDoGroups;

CREATE TABLE ToDoGroups (ID BIGINT NOT NULL IDENTITY, Name VARCHAR(50) NOT NULL, UserSettingsId BIGINT NOT NULL, PRIMARY KEY (ID));

ALTER TABLE ToDoGroups ADD FOREIGN KEY (UserSettingsID) REFERENCES UserSettings (ID);

drop fk尝试执行

alter table ToDoGroups drop constraint FK790BA1FAFE315596
java.sql.SQLException: Constraint not found FK790BA1FAFE315596 in table: TODOGROUPS in statement [alter table ToDoGroups drop constraint FK790BA1FAFE315596]

尝试删除由于我在create.sql脚本中设置的约束而失败的表

    drop table ToDoGroups if exists
java.sql.SQLException: Table is referenced by a constraint in table SYS_REF_SYS_FK_808_810 table: TODOITEMS in statement [drop table ToDoGroups if exists]

更新

我还注意到hibernate在它创建表之前首次启动时(所以这是在我的脚本运行之前),尝试删除外键以删除任何存在的表。

那么hibernate如何知道使用什么外键?它使用与

相同的密钥

它执行的第一个语句

alter table ToDoGroups drop constraint FK790BA1FAFE315596

然后它会删除所有表

drop table ToDoGroups if exists

然后创建表

create table ToDoGroups (
    id bigint generated by default as identity (start with 1),
    Name varchar(50),
    UserSettingsId bigint,
    primary key (id)
)

然后它添加相同的FK

alter table ToDoGroups 
    add constraint FK790BA1FAFE315596 
    foreign key (UserSettingsId) 
    references UserSettings

我认为我的问题是hibernate如何知道要使用什么FK。当甚至没有表时,它在第一个drop语句中使用相同的FK。后来它使用了一些FK来创建关系。不应该先休眠检查表是否存在,然后尝试确定什么是FK?

1 个答案:

答案 0 :(得分:3)

据我所知,你的问题是你自己的脚本和hibernate不使用相同的约束名。

您可以使用此注释在您的关系中指定hibernate使用的约束名称:

@ForeignKey(name = "fk_UserSettings")

另外,在你的create.sql:

ALTER TABLE ToDoGroups ADD CONSTRAINT fk_UserSettings FOREIGN KEY (UserSettingsID) REFERENCES UserSettings (ID);

  

我认为我的问题是hibernate如何知道要使用什么FK。当甚至没有表时,它在第一个drop语句中使用相同的FK。后来它使用了一些FK来创建关系。不应该先休眠检查表是否存在,然后尝试确定什么是FK?

hibernate使用的外键名称是

的串联
"FK_" + hashcode of referenced entity name + hash code of referenced columns name on that entity.

因此,它不是随机生成的密钥(如果更改实体名称,您将看到它会发生变化)。这就是hibernate如何知道要丢弃的fk的名称(hibernate期望约束是由hibernate用这个众所周知的命名策略创建的)。

Hibernate使用约束的名称来操纵它。它不会比较与表关联的约束中编码的“规则”,以查看约束是否已经存在。