与 MySQL 数据库上的外复合键相关的多对一休眠映射中的未知错误

问题描述

我正在尝试映射 Real_States:

CREATE TABLE REAL_STATES (
address VARCHAR(30) NOT NULL,admin_id VARCHAR(15) NOT NULL,real_state_type_id INT(6) NOT NULL,block VARCHAR(3) NOT NULL,internal_id INT(5) NOT NULL,PRIMARY KEY (address,block,internal_id),FOREIGN KEY (real_state_type_id) REFERENCES REAL_STATE_TYPES (real_state_type_id),FOREIGN KEY (admin_id) REFERENCES ADMINS (admin_id)
);

与居民相关:

CREATE TABLE RESIDENTS (
resident_id VARCHAR(15) NOT NULL,resident_name VARCHAR(20) NOT NULL,resident_last_name VARCHAR(20) NOT NULL,resident_phone_number VARCHAR(15) NOT NULL,address VARCHAR(30) NOT NULL,PRIMARY KEY (resident_id),FOREIGN KEY (address,internal_id) REFERENCES REAL_STATES (address,internal_id)
);

通过 Real_State 的实体:

@Entity
@Table(name = "real_states")
public class RealState implements Serializable{
    private static final long serialVersionUID = 4033627448194380926L;
    @EmbeddedId
    private RealStateID realStateID;
    @Column(name = "real_state_type_id")
    @Enumerated(EnumType.ORDINAL)
    private RealStateEnum realStateEnum;
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "admin_id",insertable = true)
    private Admin admin;
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumns({@JoinColumn(name="address",referencedColumnName = "address",insertable = false,updatable = false),@JoinColumn(name="block",referencedColumnName = "block",@JoinColumn(name="internal_id",referencedColumnName = "internal_id",updatable = false)})
    private Resident resident;

带有组合键的嵌入实体:

@Embeddable
public class RealStateID  implements Serializable{
    private static final long serialVersionUID = 6485406412363395170L;
    @Column(name = "address")
    private String address;
    @Column(name = "block")
    private String block;
    @Column(name = "internal_id")
    private int internal_id;

和居民实体:

@Entity
@Table(name = "residents")
public class Resident implements Serializable {
    private static final long serialVersionUID = -9052313410222202916L;
    @Id
    @Column(name = "resident_id")
    private String resident_id;
    @Column(name = "resident_name")
    private String resident_name;
    @Column(name = "resident_last_name")
    private String resident_last_name;
    @Column(name = "resident_phone_number")
    private String resident_phone_number;
    @Column(name = "address")
    private String address;
    @Column(name = "block")
    private String block;
    @Column(name = "internal_id")
    private int internal_id;
    @OnetoMany(mappedBy = "resident",fetch= FetchType.EAGER)
    private List<RealState> realStates;

对于这种特定情况,我收到下一个错误

22:18:32,825 WARN  [org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl] (ServerService Thread Pool -- 79) GenerationTarget encountered exception accepting command : Error executing DDL "alter table real_states add constraint FKeggvad6claf4gvemna1xdk2tm foreign key (address,internal_id) references residents (address,internal_id)" via JDBC Statement: org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table real_states add constraint FKeggvad6claf4gvemna1xdk2tm foreign key (address,internal_id)" via JDBC Statement
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applysqlString(AbstractSchemaMigrator.java:559)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applysqlStrings(AbstractSchemaMigrator.java:504)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applyForeignKeys(AbstractSchemaMigrator.java:433)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:249)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:114)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:183)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72)
    at org.hibernate@5.3.20.Final//org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:310)
    at org.hibernate@5.3.20.Final//org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467)
    at org.hibernate@5.3.20.Final//org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1250)
    at org.hibernate.jipijapa-hibernate5-3@23.0.1.Final//org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
    at org.jboss.as.jpa@23.0.1.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:170)
    at org.jboss.as.jpa@23.0.1.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:128)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at org.wildfly.security.elytron-private@1.15.3.Final//org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:664)
    at org.jboss.as.jpa@23.0.1.Final//org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:213)
    at org.jboss.threads@2.4.0.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
    at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
    at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
    at java.base/java.lang.Thread.run(Thread.java:834)
    at org.jboss.threads@2.4.0.Final//org.jboss.threads.JBossthread.run(JBossthread.java:513)
Caused by: java.sql.sqlIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`real_state`.`#sql-3e28_118`,CONSTRAINT `FKeggvad6claf4gvemna1xdk2tm` FOREIGN KEY (`address`,`block`,`internal_id`) REFERENCES `residents` (`address`,`internal_id`))
    at com.MysqL@8.0.22//com.MysqL.cj.jdbc.exceptions.sqlError.createsqlException(sqlError.java:117)
    at com.MysqL@8.0.22//com.MysqL.cj.jdbc.exceptions.sqlError.createsqlException(sqlError.java:97)
    at com.MysqL@8.0.22//com.MysqL.cj.jdbc.exceptions.sqlExceptionsMapping.translateException(sqlExceptionsMapping.java:122)
    at com.MysqL@8.0.22//com.MysqL.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:764)
    at com.MysqL@8.0.22//com.MysqL.cj.jdbc.StatementImpl.execute(StatementImpl.java:648)
    at org.jboss.ironjacamar.jdbcadapters@1.4.27.Final//org.jboss.jca.adapters.jdbc.WrappedStatement.execute(WrappedStatement.java:198)
    at org.hibernate@5.3.20.Final//org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54)
    ... 22 more

在此之前,我收到一个错误,要求我实现“插入应该是假的,更新应该是假的”,这就是为什么我将这些语句添加到每个 @JoinColumn 注释中的原因,我真的是 JPA 的新手,所以我非常感谢任何可以指导我找出此问题背后原因的建议或帮助。

解决方法

如果您尝试保存或更新 realstates,请确保将 resident 对象正确设置为 realstate。错误日志显示保存 realstates 时存在外键冲突,这发生在 realstate 对象在保存时没有 resident 对象。

,

根据您的 RESIDENTS 表定义:

CREATE TABLE RESIDENTS (
  -- ...
  FOREIGN KEY (address,block,internal_id) REFERENCES REAL_STATES (address,internal_id)
);

Resident - RealState 关联的所有者端应在 Resident 实体中定义,如下所示:

@Entity
@Table(name = "residents")
public class Resident implements Serializable {
   // ...

   @ManyToOne
   @JoinColumns({
      @JoinColumn(name="address",referencedColumnName = "address"),@JoinColumn(name="block",referencedColumnName = "block"),@JoinColumn(name="internal_id",referencedColumnName = "internal_id")
   })
   private RealState realState;
}

然后是 mappedBy 实体中的 RealState 端。

@Entity
@Table(name = "real_states")
public class RealState implements Serializable {
   // ...
   @OneToMany(mappedBy = "realState",fetch= FetchType.EAGER,cascade = CascadeType.ALL)
   private List<Resident> resident;
}