Issue
I have example code to check how bidirectional relationship works.
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class A {
@Id
@GeneratedValue
private long aId;
String name;
String address;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "b_id_FK")
B b;
}
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class B {
@Id
@GeneratedValue
@Column(name = "b_id_PK")
private long bId;
private String name;
private String address;
@JoinColumn(name = "a_id", referencedColumnName = "aId")
@OneToOne(mappedBy = "b", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
A a;
}
public void insertAB(){
B b = new B();
b.setName("B-Name");
b.setAddress("B-Address");
A a = new A();
a.setName("A-Name");
a.setAddress("A-Address");
a.setB(b);
b.setA(a);
aRepository.save(a);
}
I can see this kind of table h2 table:-
A:-
B:-
For the B table I was expecting a column a_id
as I mentioned in the code.
So I in my controller if I try to retrieve B as this:-
@GetMapping(value = "/getb/{id}")
public B getB(@PathVariable long id){
var b = bRepository.findById(id).get();
return b;
}
{
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
"b": {
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
"b": {
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
...........
It is like chain of A an B many of them. I am learning hibernate and table relationship. Obviously I misunderstand something. My intention is for bidirectional is that When I load A, I can access related B. Also when I load B, I can access related A. How can I achieve this goal?
Solution
For the bidirectional one-to-one relationship this kind of annotation worked for me:-
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class A {
@Id
@GeneratedValue
private long aId;
String name;
String address;
@JsonManagedReference // this for parent to avoid infinite recursion
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "b_id_FK") // B table foreign key in A table
B b;
}
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class B {
@Id
@GeneratedValue
@Column(name = "b_id_PK")
private long bId;
private String name;
private String address;
@NotNull
@JsonBackReference // this for child to avoid infinite recursion
@JoinColumn(name = "a_id_FK") // A table foreign key in B table
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private A a;
}
This way I can have foreign key in both A and B table. So I can access bidirectionally.
Answered By - Masi Boo
Answer Checked By - Robin (JavaFixing Admin)