0

0

解决Spring JPA外键约束创建错误:复合主键的正确处理

DDD

DDD

发布时间:2025-08-24 17:30:16

|

232人浏览过

|

来源于php中文网

原创

解决spring jpa外键约束创建错误:复合主键的正确处理

本文旨在帮助开发者解决在使用Spring JPA映射具有复合主键的数据库表时,遇到的外键约束创建错误。通过示例代码,详细解释了如何定义复合主键类,并在实体类中正确使用,最终成功创建外键关系,避免number of referencing and referenced columns for foreign key disagree错误。

在使用Spring JPA进行数据库映射时,如果数据库表使用了复合主键,那么在创建外键约束时可能会遇到问题。本文将详细介绍如何正确处理这种情况,并提供示例代码,帮助开发者避免number of referencing and referenced columns for foreign key disagree错误。

复合主键的定义

当一个表的主键由多个列组成时,就称为复合主键。在JPA中,我们需要创建一个单独的类来表示这个复合主键。这个类需要满足以下条件:

  1. 必须实现 Serializable 接口。
  2. 需要使用 @Embeddable 注解标记。
  3. 需要重写 equals() 和 hashCode() 方法,确保对象比较的正确性。
  4. 对于复合主键中的每个字段,需要使用 @Column 注解指定对应的列名。
  5. 如果复合主键中包含外键,则需要使用 @ManyToOne 和 @JoinColumn 注解来建立关系。

例如,假设有一个 ClienteModel 表,其主键由 codigo 和 empresa 两个字段组成,那么可以创建一个 IdClienteModel 类来表示这个复合主键:

package com.agilsistemas.construtordepedidos.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

@Embeddable
@Getter
@Setter
@EqualsAndHashCode
@AllArgsConstructor
public class IdClienteModel implements Serializable {

    @Column(name = "codigo")
    private int idCliente;

    @ManyToOne
    @JoinColumn(name = "empresa")
    private EmpresaModel idEmpresa;

}

在这个例子中,IdClienteModel 类使用了 @Embeddable 注解,并且实现了 Serializable 接口。idCliente 字段使用了 @Column 注解指定了对应的列名为 codigo。idEmpresa 字段使用了 @ManyToOne 和 @JoinColumn 注解,表示 IdClienteModel 与 EmpresaModel 之间存在多对一的关系,并且通过 empresa 列进行关联。

实体类中使用复合主键

定义好复合主键类后,需要在实体类中使用 @EmbeddedId 注解来标记主键字段。例如,在 ClienteModel 类中,可以这样使用 IdClienteModel:

阿里妈妈·创意中心
阿里妈妈·创意中心

阿里妈妈营销创意中心

下载
package com.agilsistemas.construtordepedidos.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "tbcadastro")
public class ClienteModel implements Serializable {

    @EmbeddedId
    private IdClienteModel idCliente; //using the object as the ID

    @Column(name = "razao")
    String razaoSocial;

    @Column(name = "logradouro")
    String rua;

    @Column(name = "numero")
    String numero;

    @Column(name = "bairro")
    String bairro;

    @Column(name = "complemento")
    String complemento;

    @Column(name = "cidade")
    String cidade;

    @Column(name = "fixo")
    String telefoneFixo;

    @Column(name = "celular")
    String celular;

    @Column(name = "cliente")
    String cliente;

}

在这个例子中,idCliente 字段使用了 @EmbeddedId 注解,表示它是一个复合主键,并且类型为 IdClienteModel。

建立外键关系

当需要在另一个实体类中引用 ClienteModel 作为外键时,需要使用 @JoinColumns 注解来指定多个关联列。例如,在 PedidoModel 类中,如果需要引用 ClienteModel 作为外键,可以这样使用:

@OneToOne
@JoinColumns({
        @JoinColumn(name = "fk_cliente", referencedColumnName = "codigo", insertable = false, updatable = false),
        @JoinColumn(name = "fk_empresa", referencedColumnName = "empresa", insertable = false, updatable = false) })
ClienteModel fkCliente;

在这个例子中,@JoinColumns 注解指定了两个 @JoinColumn,分别对应 ClienteModel 的 codigo 和 empresa 两个主键字段。name 属性指定了 PedidoModel 表中的外键列名,referencedColumnName 属性指定了 ClienteModel 表中对应的列名。insertable = false 和 updatable = false 属性表示这个外键关系不参与插入和更新操作,通常用于只读关系。

注意事项

  • 确保复合主键类正确实现了 equals() 和 hashCode() 方法,否则可能会导致JPA无法正确识别对象。
  • 在使用 @JoinColumns 注解时,需要确保所有的主键字段都包含在内,并且列名对应正确。
  • 如果数据库表已经存在,并且已经定义了外键约束,那么JPA可能会尝试重新创建这些约束,导致错误。可以通过配置 spring.jpa.hibernate.ddl-auto 属性来控制JPA的DDL生成行为。例如,设置为 validate 可以让JPA只验证数据库结构,而不进行修改。

总结

通过以上步骤,我们可以正确地处理Spring JPA中具有复合主键的数据库表,并成功创建外键关系。关键在于正确定义复合主键类,并在实体类中使用 @EmbeddedId 和 @JoinColumns 注解。希望本文能够帮助开发者解决相关问题,提高开发效率。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

161

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

89

2026.01.26

hibernate和mybatis有哪些区别
hibernate和mybatis有哪些区别

hibernate和mybatis的区别:1、实现方式;2、性能;3、对象管理的对比;4、缓存机制。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

159

2024.02.23

Hibernate框架介绍
Hibernate框架介绍

本专题整合了hibernate框架相关内容,阅读专题下面的文章了解更多详细内容。

96

2025.08.06

Java Hibernate框架
Java Hibernate框架

本专题聚焦 Java 主流 ORM 框架 Hibernate 的学习与应用,系统讲解对象关系映射、实体类与表映射、HQL 查询、事务管理、缓存机制与性能优化。通过电商平台、企业管理系统和博客项目等实战案例,帮助学员掌握 Hibernate 在持久层开发中的核心技能。

39

2025.09.02

Hibernate框架搭建
Hibernate框架搭建

本专题整合了Hibernate框架用法,阅读专题下面的文章了解更多详细内容。

72

2025.10.14

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1971

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

658

2025.10.17

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号