java - JPA hibernate 中一对一关系中的外键约束

标签 java mysql spring hibernate jpa

我有两个实体 AB 具有一对一的关系。当我想将它们插入数据库时​​,出现以下错误:

Cannot add or update a child row: a foreign key constraint fails (mydb.a, CONSTRAINT FK_77pkrkrin5nqsx16b6nw6k9r7 FOREIGN KEY (id) REFERENCES b (b_id))

@JsonInclude(JsonInclude.Include.NON_NULL)     
@JsonIgnoreProperties(ignoreUnknown = true, value={"hibernateLazyInitializer", "handler"})
@Generated("org.jsonschema2pojo")
@Inheritance(strategy = InheritanceType.JOINED)
@Entity
public class A {

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

  @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
  @PrimaryKeyJoinColumn(referencedColumnName="AId")
  @JsonIgnore
  private B b;

}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true, value = {"hibernateLazyInitializer", "handler"})
@Generated("org.jsonschema2pojo")
@Entity
public class B {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private int bId;

  @OneToOne()
  @JsonIgnore
  private A a;

}

如果我删除 optional=false,插入操作将完美运行。我在将对象插入 DB 之前检查了这些对象,并确保 A 包含 B 并且 B 包含 A

AB 创建的 SQL 脚本是:

Hibernate: create table b (b_id integer not null auto_increment, string_results longtext, a_id integer, primary key (b_id))

Hibernate: create table a (id integer not null auto_increment, primary key (id))

Hibernate: alter table b add constraint FK_o3oen721etlltdc7ls82524nh foreign key (detail_id) references a (id)

Hibernate: alter table a add constraint FK_77pkrkrin5nqsx16b6nw6k9r7 foreign key (id) references b (b_id)

最佳答案

当我看到下面这句话时:

I checked the objects before inserting them into DB and I make sure that A contains B and B contains A.

我猜您想创建双向一对一关系。如果是这样,则您当前的映射无法按预期工作。让我们看看JPA 2.0 spec是什么(下载链接)说明这一点以了解此事:

Relationships may be bidirectional or unidirectional. A bidirectional relationship has both an owning side and an inverse (non-owning) side. A unidirectional relationship has only an owning side. The owning side of a relationship determines the updates to the relationship in the database, as described in section 3.2.4.

The following rules apply to bidirectional relationships:

• The inverse side of a bidirectional relationship must refer to its owning side by use of the mappedBy element of the OneToOne, OneToMany, or ManyToMany annotation. The mappedBy element designates the property or field in the entity that is the owner of the relationship.

•The many side of one-to-many / many-to-one bidirectional relationships must be the owning side, hence the mappedBy element cannot be specified on the ManyToOne annotation.

• For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.

• For many-to-many bidirectional relationships either side may be the owning side.

因此,根据双向一对一关系中的规范,必须将其中一个实体设为拥有方,而另一个设为相反方。假设实体 A 是以下映射应该起作用的拥有方:

@Entity
public class A {

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

   @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
   @JoinColumn(name="b_id", referencedColumnName="ID")
   private B b;

}

@Entity
public class B {

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

    @OneToOne(mappedBy = "b")
    private A a;

}

为了使上述映射工作,物理表必须自动生成,或者如果您想自己创建表,则相应的 SQL 应如下所示:

create table a (id integer not null auto_increment,
                b_id integer not null,
                primary key (id),
                foreign key b_id references b (id));

create table b (id integer not null auto_increment, 
                string_results longtext, 
                primary key (id));

注意:

  1. 我删除了特定于 JSON 的注释以使代码更短(我对此一无所知)

  2. 如果要使实体 B 成为拥有方,则必须相应地调整关系映射。

  3. @JoinColumn 注释始终在拥有方。

  4. 由于时间不够,我还没有测试代码。如果您发现任何错误(尤其是 MySQL 语法),请给我留言。

关于java - JPA hibernate 中一对一关系中的外键约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38368175/

相关文章:

java - Spring MVC中如何使用anchor标签在当前jsp中找到固定位置?

mysql - 如何从mysql上的每个类别获取最大id?

php - 为什么 $value = $_POST ['businessname' ]; 不从输入表单中读取姓名?

java - 处理多线程/传出 http 请求

java - 设置 ImageView 位置 - Android

java - 在 PLSQL Oracle 中抛出特定的错误消息...进入 hibernate 状态?

java - 将文本文件放在Android目录中的位置

php - 从 php 文件到 phpmyadmin 的数据库连接失败?

spring - 在不创建 Web 套接字消息代理 Spring 4 的情况下使用 SimpMessagingTemplate

spring data elasticsearch错误页面totalPages