1

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:-

enter image description here

B:-

enter image description here

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?

Masi Boo
  • 635
  • 1
  • 10
  • 24

1 Answers1

0

This solution is not ideal, because :

  • this will only remove the excessive datas from the json.
  • Hibernate will do the same request and this risks to slow down your application.
  • Not a good practise to set a jackson annotation (@JsonManagedReference) in a java entity.

==> You probably have to change relation-type

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.

Main
  • 3
  • 1
Masi Boo
  • 635
  • 1
  • 10
  • 24