22
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-08-27

概要

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?