首页 > 解决方案 > hibernate 说表不存在,但它正在创建表

问题描述

我正在开发一个 Spring 应用程序,并且我将 JPA 与 MariaDB 一起用于我的数据库。当应用程序启动时,它首先会抛出一些关于不存在的表的异常,但它会创建它们。错误后应用程序不会终止。

难道我做错了什么?

更新:

当我改变

spring.jpa.hibernate.ddl-auto=create-drop

spring.jpa.hibernate.ddl-auto=update

hibernate 不再抛出异常。

为什么?

日志总结:

    org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table roles_privileges drop foreign key FK5yjwxw2gvfyu76j3rgqwo685u" via JDBC Statement
...

Caused by: java.sql.SQLSyntaxErrorException: (conn=105) Table 'users.roles_privileges' doesn't exist
...

Caused by: java.sql.SQLException: Table 'users.roles_privileges' doesn't exist
...
2019-10-29 18:13:00.866  WARN 821 --- [           main] o.h.t.s.i.ExceptionHandlerLoggedImpl     : GenerationTarget encountered exception accepting command : Error executing DDL "alter table roles_privileges drop foreign key FK9h2vewsqh8luhfq71xokh4who" via JDBC Statement
...
Caused by: java.sql.SQLSyntaxErrorException: (conn=105) Table 'users.roles_privileges' doesn't exist

用户实体:

    @Entity
    public class User implements UserDetails {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private long id;

        @Email
        private String email;

        @Column(nullable = false, unique = true)
        private String username;

        @Column(nullable = false)
        private String password;


        @ManyToMany
        @JoinTable(
                name = "users_roles",
                joinColumns        = @JoinColumn(name = "user_id", referencedColumnName = "username"),
                inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "name"))
        private Collection<Role> roles;
...
    }

角色实体:

@Entity
    public class Role {

        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private long id;

        @Column(unique = true, nullable = false)
        private String name;

        @ManyToMany(mappedBy = "roles")
        private Collection<User> users;

        @ManyToMany
        @JoinTable(name = "roles_privileges",
        joinColumns        = @JoinColumn(name = "role_id",      referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id")
        )
        private Collection<Privilege> privileges;
...
    }

特权实体:

@Entity
    public class Privilege {

        @Id
        private long id;

        @Column(unique = true, nullable = false)
        private String name;

        @ManyToMany(mappedBy = "privileges")
        private Collection<Role> roles;
....
    }

应用程序属性

#User datasource
spring.datasource.url=jdbc:mariadb://localhost:3306/users
spring.datasource.username=user01
spring.datasource.password=user01pass

#`hibernate_sequence' doesn't exist
spring.jpa.hibernate.use-new-id-generator-mappings=false

spring.jpa.hibernate.ddl-auto=create-drop

标签: springhibernatejpa

解决方案


你可能没有做错任何事。

当您将 Hibernate 的 hbm2ddl auto 与createor一起使用时create-drop,Hibernate 将尝试在启动时创建您的数据库模式。

您可以打开您的show-sql属性application.properties以查看生成的 SQL 查询:

spring.jpa.show-sql=true

查询可能如下所示:

alter table `your_table` drop foreign key `FK...`
drop table if exists `your_table`
create table `your_table` (...)
alter table `your_table` add constraint `UK...` unique (`name`)
alter table `your_table` add constraint `FK...` foreign key (`foreign_id`) references `other_table` (`id`)

首先 Hibernate 删除外键约束,然后删除表,然后创建表,然后对其添加约束。

该错误发生在第一个查询中,当尝试删除外键并且表还不存在时。没有什么不好的事情发生,您可以忽略错误,其他查询将起作用并且表将被正确创建。

据我所知,MySQL 和 MariaDB 不支持“如果表存在则删除外键”之类的东西,这将有助于抑制错误。


推荐阅读