[Java] エンティティのJSON化において、無限ループを防ぐ
概要
エンティティAとBの2つがあります。
AとBは双方向にリレーションシップをはっています。
ここでAをJSONシリアライズすると……
Aをシリアライズ
↓
AからリレーションシップをたどってBもシリアライズ
↓
BからリレーションシップをたどってAをシリアライズ
↓
・
・
・
(以下続く)
というように、無限ループになってしまいます。これを防ぐ方法です。
方法1:シリアライズを一方向に制限する
リレーションシップは双方向のままで、シリアライズのみを一方向にできます。
AをシリアライズしたときはBもシリアライズします。けど、BをシリアライズしたときはAをシリアライズしません。
方法は、A側に@JsonManagedReference
アノテーションをつけ、B側に@JsonBackReference
をつけます。
A.java
@Entity
class A implements Serializable {
@OneToMany(mappedBy="a")
@JsonManagedReference
private List<B> bList;
}
B.java
@Entity
class B implements Serializable {
@ManyToOne
@JsonBackReference
private A a;
}
Aをシリアライズすると、このようになります。
{
b: [
{ }
]
}
方法2:複数回登場するエンティティは、IDに置き換える
エンティティクラスに@JsonIdentityInfo
をつけると、シリアライズ時にIDを発行し、同じエンティティを参照するときはIDに置き換わります。
A.java
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
class A implement Serializable {
@OneToMany(mappedBy="a")
private List<B> bList;
}
B.java
@Entity
class B implements Serializable {
@ManyToOne
private A a;
}
Aをシリアライズすると、このようになります。
{
@Id: 1
b: [
{ a: 1 } /* @Id=1のオブジェクトを参照している */
]
}