1

我正在尝试了解一对一映射类的 JPA Spring Boot 实现,并希望是否有人可以为我提供清晰的图片。

  1. 一对一映射场景:表 foo 和表 childfoo Foo 具有列 foo_id,foo_name, foo_place childfoo 具有列 foo_id(foo 表的外键), childfoo_name

这是我到目前为止所做的 JPA 实体实现:

@Entity
@Data
@Table(name = "foo")
public class foo implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "foo_id")
private Integer fooId;

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name="fooId")
private ChildFoo childFoo;
}

ChildFoo 类

@Entity
@Data
@NoArgsConstructor
@EqualsAndHashCode(exclude ="foo")
@Table(name = "childfoo")
public class Childfoo implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -8142203085486540150L;
    
    @Id
    private Integer fooId;

    @OneToOne(cascade = CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
    @PrimaryKeyJoinColumn(name = "foo_id", referencedColumnName = "fooId")
    private Foo foo;
    
    @Column(name="child_name")
     private String childName;

   }

我已经为 Foo 创建了一个存储库,并 FooRepository.save(foo) 在控制器中使用它来保存数据。

添加 foo 和 childfoo 的控制器代码:

Foo foo = new Foo();
foo.set...

   ChildFoo childFoo = new ChildFoo();
        childFoo.setChildName("abc");
        childFoo.setFoo(foo);

foo.setChildFoo(childFoo);
fooRepository.save(foo);


 

但我收到错误:

必须在调用 save() 之前手动分配此类的 ID。

4

1 回答 1

2

从您的评论看来,您正在尝试使用共享主键策略,该策略ChildFoo也将fooId用作其自己的主键。

如果是这种情况,那么我认为您需要更新一些 JPA 注释:

@Entity
@Data
@Table(name = "foo")
public class Foo implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "foo_id")
    private Integer fooId;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "foo")
    private ChildFoo childFoo;

}


@Entity
@Data
@NoArgsConstructor
@EqualsAndHashCode(exclude ="foo")
@Table(name = "childfoo")
public class ChildFoo implements Serializable {

    private static final long serialVersionUID = -8142203085486540150L;
    
    @Id
    @Column(name = "foo_id")
    private Integer fooId;

    @OneToOne(cascade = CascadeType.ALL, optional = false)
    @MapsId // primary key copied from Foo
    @JoinColumn(name = "foo_id")
    private Foo foo;
    
    @Column(name="child_name")
     private String childName;

}

在关联和保存 之前,您可能需要保存 的实例Foo(从而生成共享 ID)ChildFoo,但我认为一旦所有内容都得到正确注释,就没有必要这样做了。

说到注释,我只是从您的原始注释中删除了惰性获取类型以澄清更新。您应该能够毫无问题地包含它们。

其他有用的链接: 与 JPA 共享主键和 Spring Boot OneToOne 共享主键 - JPA2.0 更新

于 2021-05-11T04:26:17.127 回答