我遇到一个问题,即hibernate试图删除不存在的外键而不是存在的外键。我的场景看起来像这样。
我想运行junit测试,在测试之前我想要创建数据库,并且在测试之后我想删除它。为此我使用了hibernate create-drop属性。然而,棘手的部分是我想创建自己的表作为测试新添加的sql的一种方法,并验证一旦我将它部署到生产数据库服务器就可以正常运行。那么会发生什么呢
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?
答案 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使用约束的名称来操纵它。它不会比较与表关联的约束中编码的“规则”,以查看约束是否已经存在。