【问题标题】:Hibernate cannot rebuild tables due to broken foreign keys由于外键损坏,Hibernate 无法重建表
【发布时间】:2017-03-11 22:59:00
【问题描述】:

好吧,我有一个使用 Hibernate (5.0.12.Final) 的 Spring Boot 应用程序 (1.5.2.RELEASE),我遇到了一些问题,即 Hibernate 无法在启动时正确重新创建我的数据库.

我将 Hibernate 配置为在启动时再次创建表:

spring.jpa.hibernate.ddl-auto=create

这是我的第一个实体(客户):

@Entity
public class Client {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private String name;

    @NotNull
    private String firstName;

    @Email
    @NotNull
    private String email;

    @Valid
    @Embedded
    private Credentials credentials = new Credentials();

    @OneToMany(mappedBy = "client")
    private List<Reservation> reservations = new ArrayList<>();

    //Getters, Setters, hashcode & equals omitted
}

预订实体:

@Entity
public class Reservation {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    private Client client;

    @Enumerated(EnumType.STRING)
    private State state = State.UNTREATED;
    
    //Getters, Setters, hashcode & equals omitted
}

这里是创建的数据库的概述:

这是控制台输出,为简单起见,我尝试将其缩写:

INFO : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
INFO : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
INFO : HHH000227: Running hbm2ddl schema export

Hibernate: alter table reservation drop foreign key FKoewar6f18rkn4iptr6da4oysv

ERROR : HHH000389: Unsuccessful: alter table reservation drop foreign key FKoewar6f18rkn4iptr6da4oysv
ERROR : Can't DROP 'FKoewar6f18rkn4iptr6da4oysv'; check that column/key exists

Hibernate: drop table if exists client

ERROR : HHH000389: Unsuccessful: drop table if exists client
ERROR : Cannot delete or update a parent row: a foreign key constraint fails

Hibernate: drop table if exists reservation
Hibernate: drop table if exists restaurant
Hibernate: create table client (id bigint not null auto_increment, created_on datetime, credentials_version integer not null, hash varchar(255), username varchar(255), email varchar(255) not null, first_name varchar(255) not null, name varchar(255) not null, primary key (id))

ERROR : HHH000389: Unsuccessful: create table client (id bigint not null auto_increment, created_on datetime, credentials_version integer not null, hash varchar(255), username varchar(255), email varchar(255) not null, first_name varchar(255) not null, name varchar(255) not null, primary key (id))
ERROR : Table 'client' already exists

Hibernate: create table reservation (id bigint not null auto_increment, state varchar(255), client_id bigint, primary key (id))
Hibernate: create table restaurant (id bigint not null auto_increment, primary key (id))
Hibernate: alter table reservation add constraint FKoewar6f18rkn4iptr6da4oysv foreign key (client_id) references client (id)

 INFO  : HHH000230: Schema export complete
 INFO  : Initialized JPA EntityManagerFactory for persistence unit 'default'
 INFO  : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
 INFO  : HHH000227: Running hbm2ddl schema export
ERROR  : HHH000389: Unsuccessful: alter table `Reservation` drop foreign key `FK8gjvlt7rp8i9kp7rdmn107ni7`
ERROR  : Can't DROP 'FK8gjvlt7rp8i9kp7rdmn107ni7'; check that column/key exists
ERROR  : HHH000389: Unsuccessful: drop table if exists `Client`
ERROR  : Cannot delete or update a parent row: a foreign key constraint fails
ERROR  : HHH000389: Unsuccessful: create table `Client` (`id` bigint not null auto_increment, `createdOn` datetime, `credentialsVersion` integer not null, `hash` varchar(255), `username` varchar(255), `email` varchar(255) not null, `firstName` varchar(255) not null, `name` varchar(255) not null, primary key (`id`))
ERROR  : Table 'client' already exists
 INFO  : HHH000230: Schema export complete

我不知道这是否重要,但 MySQL 数据库版本是在 Windows 上运行的 5.7.13。此外,我没有包括 Restaurant 实体和可嵌入的 Credentials。

我觉得奇怪的是,Hibernate 试图先删除一个不存在的外键,然后再删除正确的外键,但都失败了(如果我没看错的话)。

这背后的原因/原因是什么?以及如何预防这些问题?

我查看了其他相关的 SO 问题,它们通常是由无效名称或类似名称引起的,但我认为我的命名没有任何问题。我还尝试使用“tbl_”为所有表添加前缀,并使用前缀重命名某些列,以防万一发生冲突但没有运气。

这让我很困扰,因为数据库没有正确更新,并且在积极开发期间,我不想每次都手动删除/创建架构。也许值得一提的是,即使 schema 是空的,在启动时,hibernate 也会给出东西不存在的错误。

【问题讨论】:

    标签: java mysql spring hibernate jpa


    【解决方案1】:

    试试看。我认为预订有问题

    @ManyToOne
    @JoinColumn(name = "client_id")
    private Client client;
    

    【讨论】:

    • 你好,我相信client_id已经是它默认的名字了。
    【解决方案2】:

    首先,您应该了解外键约束名称是如何生成的:

    How does hibernate generate foreign key constraint names?

    因此,如果您更改表或外键列名称,您将拥有不同的外键约束名称,Hibernate 将无法删除旧的外键约束。

    你可以做什么:

    1. 使用指定外部约束名称 @javax.persistence.ForeignKey 注解(不要与 @org.hibernate.annotations.ForeignKey,虽然可以用 到)。

    2. 使用spring.jpa.hibernate.ddl-auto = update 仅更新架构, 不要每次都重新创建它。

    3. 使用命名策略生成外键名称(仅适用于 Hibernate 5)。但是您需要考虑如何组合表、关联表、列名称以不经常更改外部约束名称:Need help in implementing ImplicitNamingStrategy for foreign key column names in Hibernate 5

    【讨论】:

    • 谢谢你的回答,但是即使我跨多代和初创公司不改变任何东西,它仍然无法删除外键。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 2013-05-24
    • 1970-01-01
    • 2014-12-21
    • 2018-03-15
    • 2013-04-02
    • 1970-01-01
    相关资源
    最近更新 更多