Edited at

[Java] エンティティのJSON化において、無限ループを防ぐ

More than 1 year has passed since last update.


概要

エンティティ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のオブジェクトを参照している */
]
}