Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
467 views
in Technique[技术] by (71.8m points)

hibernate - Jackson bidirectional relationship (One-to-many) not working

I'm using Spring(xml+annotations), Hibernate(annotations) in this web service project. The database relationship diagram, models, expected and actual output are given below,

Database Table relationship

Customer.java

@Entity
@Table(name="customer")
public class Customer implements Serializable{
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="customer_id", unique=true, nullable =false)
    long customerId;
    @Column(name="name")
    String name;
    @Column(name="secondary_name")
    String secondaryName;
    @Column(name="date")
    Date date;
    @Column(name="address")
    String address;
    @Column(name="post")
    String post;
    @Column(name="pin")
    String pin;
    @Column(name="phone")
    String phone;
    @OneToMany(fetch=FetchType.LAZY, mappedBy="customer", cascade=CascadeType.ALL)
    @JsonManagedReference
    Set<Loan> loans = new HashSet<Loan>();
    //constructors, getters and setters
}

Loan.java

public class Loan implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="loan_id", nullable=false, unique=true)
    long loanId;
    @ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
    @JoinColumn(name="customer_id", nullable = false)
    @JsonBackReference
    Customer customer;
    @Column(name="date", nullable=false)
    Date date;
    @Column(name="amount", nullable=false)
    double amount;
    @OneToMany(fetch=FetchType.LAZY, mappedBy="loan", cascade=CascadeType.ALL)
    @JsonManagedReference
    List<Item> items = new ArrayList<Item>();
    //constructors, getters, setters
}

Item.java

public class Item implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="item_id", nullable=false, unique=true)
    long itemId;
    @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @JoinColumn(name="loan_id", nullable = false)
    @JsonBackReference
    Loan loan;
    @Column(name="name", nullable=false)
    String name;
    @Column(name="weight", nullable=false)
    double weight;
    //constructors, setters, getters
}

Actual output:Here, customer details are not shown

{  
   "loanId":4,
   "date":1484937000000,
   "amount":10000.0,
   "items":[  
      {  
         "itemId":3,
         "name":"Item1",
         "weight":10.0
      },
      {  
         "itemId":4,
         "name":"Item2",
         "weight":20.0
      }
   ]
}

Expected output: need to display customer details also when looking for a loan

{  
   "loanId":4,
   "customer":{  
      "customerId":2,
      "name":"Prem",
      "address":"Street,State"
   },
   "date":1484937000000,
   "amount":10000.0,
   "items":[  
      {  
         "itemId":3,
         "name":"Item1",
         "weight":10.0
      },
      {  
         "itemId":4,
         "name":"Item2",
         "weight":20.0
      }
   ]
}

I can able to fetch the customer details from the database and fail to load it using Jackson Json. If I remove @JsonManagedReference, I end up with circular loop. If I remove @JsonBackReference, no effects in the output. Complete code at: https://github.com/liwevire/TM_Service Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Because you are using the @JsonBackReference on the Customer property in the Loan entity, the Customer object will not included in the serialization. Use the @JsonManagedReference for the Customer in the Loan object and use @JsonBackReference on the Loan property in the Customer entity.

This will serialize the Customer property of your Loan entity. But the Customer object serialization will not contains the Loan property. You need to pick one side of the relationship to serialize.

To allow both side, use @JsonIdentityInfo annotation in your entity and remove the @JsonBackReference and @JsonManagedReference. You entities will be something like:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "customerId")
public class Customer implements Serializable {
    ...
}

The property of the @JsonIdentityInfo refer to your entity id property, for Customer this will be customerId. Do this for Loan and Item also.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...