杰克逊双向关系(一对多)不起作用
Jackson bidirectional relationship (One-to-many) not working
我在这个 Web 服务项目中使用 Spring(xml+annotations), Hibernate(annotations)。数据库关系图、模型、预期和实际输出如下,
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
}
实际 output:Here,未显示客户详细信息
{
"loanId":4,
"date":1484937000000,
"amount":10000.0,
"items":[
{
"itemId":3,
"name":"Item1",
"weight":10.0
},
{
"itemId":4,
"name":"Item2",
"weight":20.0
}
]
}
预期输出:在寻找贷款时也需要显示客户详细信息
{
"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
}
]
}
我可以从数据库中获取客户详细信息,但无法使用 Jackson Json 加载它。
如果我删除@JsonManagedReference,我将以循环结束。
如果我删除@JsonBackReference,则输出没有任何影响。
完整代码位于:https://github.com/liwevire/TM_Service
提前致谢。
因为您在 Loan
实体的 Customer
属性 上使用 @JsonBackReference
,所以 Customer
对象将不会包含在序列化中。在 Loan
对象中对 Customer
使用 @JsonManagedReference
,在 Customer
实体中对 Loan
属性 使用 @JsonBackReference
。
这将序列化您的 Loan
实体的 Customer
属性。但是Customer
对象序列化不会包含Loan
属性。您需要选择关系的一侧进行序列化。
要允许双方,请在您的实体中使用 @JsonIdentityInfo
注释并删除 @JsonBackReference
和 @JsonManagedReference
。您的实体将类似于:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "customerId")
public class Customer implements Serializable {
...
}
@JsonIdentityInfo
的 property
引用您的实体 ID 属性,对于 Customer
,这将是 customerId
。 Loan
和 Item
也这样做。
这看起来很旧,但让我把我的硬币也放在这里;我会分开实体和模型。意思是;
> Client <-> Application : Models
>
> Application <-> Database : Entities
并且您的服务层或您处理数据的任何层都应该在实体和模型之间进行转换。
- 您可以根据需要返回数据来摆脱递归。
- 您将定义拆分到两个不同的通信渠道。通过这种方式,您可以决定向您的客户展示什么以及如何向您的客户展示。这将保存您的数据库模式也直接公开。
- 您可以根据自己的意愿扩展模型,而无需触及数据库后端。
这里的方法有点冗长。但需要在您的应用程序中进行一些设计修改。
我有一个类似的问题,我为每个实体创建了单独的 pojos 类.
在服务层中,我使用这些 pojo 而不是实体对象作为参数,并且我使用适当的 getters/setters 到 set/get 属性 to/from 实体 类。
通过这种方式,您可以 get/set 您想要的属性并避免不需要的属性。但是,我在 DAO 层中实现了其他方法来获取相关实体。这是非常冗长的方法,但为我解决了问题。
我在这个 Web 服务项目中使用 Spring(xml+annotations), Hibernate(annotations)。数据库关系图、模型、预期和实际输出如下,
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
}
实际 output:Here,未显示客户详细信息
{
"loanId":4,
"date":1484937000000,
"amount":10000.0,
"items":[
{
"itemId":3,
"name":"Item1",
"weight":10.0
},
{
"itemId":4,
"name":"Item2",
"weight":20.0
}
]
}
预期输出:在寻找贷款时也需要显示客户详细信息
{
"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
}
]
}
我可以从数据库中获取客户详细信息,但无法使用 Jackson Json 加载它。 如果我删除@JsonManagedReference,我将以循环结束。 如果我删除@JsonBackReference,则输出没有任何影响。 完整代码位于:https://github.com/liwevire/TM_Service 提前致谢。
因为您在 Loan
实体的 Customer
属性 上使用 @JsonBackReference
,所以 Customer
对象将不会包含在序列化中。在 Loan
对象中对 Customer
使用 @JsonManagedReference
,在 Customer
实体中对 Loan
属性 使用 @JsonBackReference
。
这将序列化您的 Loan
实体的 Customer
属性。但是Customer
对象序列化不会包含Loan
属性。您需要选择关系的一侧进行序列化。
要允许双方,请在您的实体中使用 @JsonIdentityInfo
注释并删除 @JsonBackReference
和 @JsonManagedReference
。您的实体将类似于:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "customerId")
public class Customer implements Serializable {
...
}
@JsonIdentityInfo
的 property
引用您的实体 ID 属性,对于 Customer
,这将是 customerId
。 Loan
和 Item
也这样做。
这看起来很旧,但让我把我的硬币也放在这里;我会分开实体和模型。意思是;
> Client <-> Application : Models
>
> Application <-> Database : Entities
并且您的服务层或您处理数据的任何层都应该在实体和模型之间进行转换。
- 您可以根据需要返回数据来摆脱递归。
- 您将定义拆分到两个不同的通信渠道。通过这种方式,您可以决定向您的客户展示什么以及如何向您的客户展示。这将保存您的数据库模式也直接公开。
- 您可以根据自己的意愿扩展模型,而无需触及数据库后端。
这里的方法有点冗长。但需要在您的应用程序中进行一些设计修改。 我有一个类似的问题,我为每个实体创建了单独的 pojos 类.
在服务层中,我使用这些 pojo 而不是实体对象作为参数,并且我使用适当的 getters/setters 到 set/get 属性 to/from 实体 类。 通过这种方式,您可以 get/set 您想要的属性并避免不需要的属性。但是,我在 DAO 层中实现了其他方法来获取相关实体。这是非常冗长的方法,但为我解决了问题。