I am trying to understand the JPA Spring Boot implementation for One-to-One mapping classes and was hoping if anyone could provide me a clear picture.
- One to One mapping Scenario: Table foo and Table childfoo Foo has the columns foo_id,foo_name, foo_place childfoo has the columnd foo_id(foreignkey of foo table), childfoo_name
Here is the JPA entity implementation I’ve made so far:
@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 class
@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; }
I’ve created a repository for the Foo and I am using
FooRepository.save(foo)
in the controller to save the data.
Controller code to add the foo and childfoo:
Foo foo = new Foo(); foo.set... ChildFoo childFoo = new ChildFoo(); childFoo.setChildName("abc"); childFoo.setFoo(foo); foo.setChildFoo(childFoo); fooRepository.save(foo);
But I am getting the error:
ids for this class must be manually assigned before calling save().
Advertisement
Answer
From your comments it appears you are trying to use a shared primary key strategy where ChildFoo
will also use fooId
as its own primary key.
If that’s the case, then I think you need to update some of your JPA annotations:
@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; }
And you may need save the instance of Foo
(thereby generating the shared Id) before associating and saving the ChildFoo
, but I don’t think that’s necessary once everything is properly annotated.
Speaking of annotations, I only removed the lazy fetch type from your original annotations to clarify updates. You should be able to include them without any issues.
Additional useful links: Shared primary key with JPA and Spring Boot OneToOne shared primary key – JPA2.0 updates