Hibernate 无法添加外键约束

Posted

技术标签:

【中文标题】Hibernate 无法添加外键约束【英文标题】:Hibernate unable to add foreign key constraint 【发布时间】:2018-05-16 06:58:57 【问题描述】:

我已经创建了具有所有外键约束的数据库和所有表。但是当我运行 Spring Boot 应用程序休眠时抛出错误

无法对 JDBC 目标执行架构管理 [alter table tlp_client 添加约束 FKfd2km387c8s4oou769dmw5t94 外键 (u_frn_address_id) 引用 tlp_address (a_id)]

实体

@Entity
@Table(name = "tlp_client")
public class ClientModel 

   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "c_id")
   private Long id;

   @Column(name = "c_name")
   private String name;

   @Column(name = "c_description")
   private String description;

   @Column(name = "c_web_url")
   private String webUrl;

   @Column(name = "c_created_at")
   private Calendar createdAt;

   @Column(name = "c_is_active")
   private Boolean isActive;

   @OneToOne
   @JoinColumn(name = "u_frn_created_by", referencedColumnName = "u_id")
   private UserModel createdBy;

   @OneToOne
   @JoinColumn(name = "u_frn_address_id", referencedColumnName = "a_id")
   private AddressModel address;

    
   // getters and setters ...

ClientModel 的 SQL

create table tlp_client (
   c_id INT(11) AUTO_INCREMENT,
   c_name varchar(255) NOT NULL,
   c_description varchar(255), 
   c_web_url varchar(255),
   c_created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
   c_is_active TINYINT(1) DEFAULT 1,

   c_frn_created_by INT(11),
   c_frn_address_id INT(11),

   PRIMARY KEY (c_id),
   FOREIGN KEY (c_frn_address_id) REFERENCES tlp_address (a_id),
   FOREIGN KEY (c_frn_created_by) REFERENCES tlp_user (u_id)
);

AddressModel的SQL

create table tlp_address (
   a_id INT(11) AUTO_INCREMENT,
   a_address varchar(255),
   a_city varchar(255),
   a_state varchar(255),
   a_country varchar(255),
   a_zip varchar(8),

   PRIMARY KEY (a_id)
);

我的问题是,我已经创建了所有的表,为什么 hibernate 还要尝试创建表?

application.properties

spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/dbName?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.pool.size=20
server.port=8090

更新 我通过在application.properties 中设置spring.jpa.hibernate.ddl-auto=validate 来运行应用程序,现在它正在抛出错误

架构验证:在 [a_id] 列中遇到错误的列类型 表[tlp_address];找到 [int (Types#INTEGER)],但期待 [bigint (Types#BIGINT)]

【问题讨论】:

【参考方案1】:

似乎原来的问题随着设置而消失了

spring.jpa.hibernate.ddl-auto=validate

新问题是因为hibernate 无法更改列类型。如果不删除并重新创建列(或整个表),无论如何 -afaik- 是不可能的

你有你的ClientModel

@Column(name = "c_id")
private Long id; // Long maps to bigint 8 bytes

但是在你的创建脚本中你有

c_id INT(11) AUTO_INCREMENT, -- int is 4 bytes

要使Long 值适合列,它应该是bigint,但您已将其创建为int。改成bigint

c_id BIGINT AUTO_INCREMENT,

并重新创建表

请参阅 this 和 this 以供参考。

【讨论】:

【参考方案2】:

这个错误是由于我犯了一个简单的错误。在 sql 脚本中,我有字段 c_frn_addres_id,但在实体类中,我将其映射到 u_frn_address_id。所以在将u_frn_address_id 更改为c_frn_address_id 后,它工作正常

【讨论】:

【参考方案3】:

“Hibernate 正在尝试创建表”,因为使用 proeprty spring.jpa.hibernate.ddl-auto 进行配置。让我们像这样改变它的价值

spring.jpa.hibernate.ddl-auto=update

您还可以参考工作示例Spring Boot JPA One to Many Relationship Mapping

【讨论】:

我也这样做了,但仍然显示相同的错误 太奇怪了。实际上,您只需拥有足够的 java 实体,然后 Hibernate/JPA 将创建/更新映射您的实体的表。 其实这是我第一次遇到这个问题【参考方案4】:

这可能有很多原因。例如,在MYSQL数据库中,您可以使用下面的链接: enter link description here

数据库开发中可能出现的常见原因之一代码和数据库中的列类型不一样。 例如:在您的实体中,“id”字段可能会导致“int(11)”,但当前数据库需要“bigint(20)”。这种干扰会导致以下错误:

Hibernate unable to add foreign key constraint

最后一步一步检查你的主外键。 希望对您有所帮助...

【讨论】:

以上是关于Hibernate 无法添加外键约束的主要内容,如果未能解决你的问题,请参考以下文章

外键 Laravel 8 foreignId + 约束 - 无法添加或更新子行:外键约束失败

错误代码:1215。无法添加外键约束(外键)

错误代码:1215。无法添加外键约束(外键)

错误代码:1215。无法添加外键约束(外键)

MySQL 无法添加外键约束

Mysql创建索引而不是外键约束