2016-11-04 17 views
0

Spring Bootでクラスをデシリアライズする際に問題があります。私のコントローラがそれを逆シリアル化しようとすると、クラッシュします。ここではクラスがある:HibernateからJSONを逆シリアル化する

この1に依存
@Entity 
@Table(name="trash_cans") 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id") 
public class TrashCan { 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    @Column(name="TRASH_CAN_ID") 
    long id; 

    @Column(name="TRASH_CAN_NAME") 
    String name; 

    @ManyToOne 
    @JoinColumn(name="PLACE_ID") 
    private Place place; 

    @OneToMany(mappedBy="trashCan", targetEntity=TrashMeter.class, fetch=FetchType.LAZY) 
    private List<TrashCan> trashMeterList; 

    @OneToMany(mappedBy="trashCan", targetEntity=TrashSensor.class, fetch=FetchType.LAZY) 
    private List<TrashSensor> trashSensorList; 

    public TrashCan() {  
    } 

    public TrashCan(long id, String name) { 
     super(); 
     this.id = id; 
     this.name = name; 
    } 

    [getters and setters] 
} 

@Entity 
@Table(name="trash_sensor") 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id") 
public class TrashSensor { 

    @Id 
    @Column(name="id") 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long id; 

    @Column(name="name") 
    private String name; 

    @Column(name="description") 
    private String description; 

    @ManyToOne 
    @JoinColumn(name="TRASH_CAN_ID") 
    private TrashCan trashCan; 

    @OneToMany(mappedBy = "trashSensor", targetEntity = Measurement.class, fetch = FetchType.LAZY) 
    private List<Measurement> measurementList; 

    public TrashSensor() { 
     super(); 
    } 

、ゴミ箱センサーは、このクラスによって異なります:

@Entity 
@Table(name="measurement") 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id") 
public class Measurement { 

    @Id 
    @Column(name="id") 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long id; 

    @Column(name="value") 
    private float value; 

    @Column(name="last_measure") 
    private LocalDateTime dateTime; 

    @ManyToOne 
    @JoinColumn(name="trash_sensor_id") 
    private TrashCan trashSensor; 

    public Measurement() { 
    } 

} 

私のcontroler:

@RequestMapping(value="/trashCan", method=RequestMethod.GET) 
    public ResponseEntity<Iterable<TrashCan>> getPlaces(){ 
     Iterable<TrashCan> trashCanIterable = trashCansRepository.findAll(); 

     return new ResponseEntity<>(trashCanIterable, HttpStatus.OK); 
    } 

私がウェブサービスを呼び出すと、私はこのror:

Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: could not deserialize (through reference chain: java.util.ArrayList[0]-br.com.simplepass.cleanerway.domain.TrashCan["trashSensorList"]-org.hibernate.collection.internal.PersistentBag[0]-br.com.simplepass.cleanerway.domain.TrashSensor["measurementList"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not deserialize (through reference chain: java.util.ArrayList[0]-br.com.simplepass.cleanerway.domain.TrashCan["trashSensorList"]-org.hibernate.collection.internal.PersistentBag[0]-br.com.simplepass.cleanerway.domain.TrashSensor["measurementList"])

私はこのエラー=/を解釈できません。この問題の助けがあれば大歓迎です。あなたは、エンティティ間の関係を使用する場合

@OneToMany(mappedBy = "trashSensor", targetEntity = Measurement.class, fetch = FetchType.LAZY) 
@JsonIgnore 
private List<Measurement> measurementList; 

答えて

1

あなたはこのエラーを取得しています。ごみ箱にゴミ箱へのリンクがあるとします。そしてごみ箱にはラッパーのごみ箱へのリンクがあります。だからあなたはまたごみをシリアライズするTrashCanエンティティをシリアル化しようとします。そして、ゴミ箱をシリアル化するとき、ゴミ箱をもう一度シリアル化します。等々。それはループです。ループを引き起こす可能性があるすべてのエンティティで@JsonIgnoreを使用できます。

@JsonIgnore 
@ManyToOne 
@JoinColumn(name="PLACE_ID") 
private Place place; 

@JsonIgnore 
@OneToMany(mappedBy="trashCan", targetEntity=TrashMeter.class, fetch=FetchType.LAZY) 
private List<TrashCan> trashMeterList; 

@JsonIgnore 
@OneToMany(mappedBy="trashCan", targetEntity=TrashSensor.class, fetch=FetchType.LAZY) 
private List<TrashSensor> trashSensorList; 

しかし、それは悪い方法です。シリアライズ/デシリアライズのためにDTO(データ転送オブジェクト)パターンを使用することを強くお勧めします。また、柔軟性も向上します。あなたがこの回答に従っ応じてtrashMeterListtrashSensorListが必要な場合には、それhere

+0

そして、はい...これが唯一のplace..youではありませんが、ループに入っているより多くのマッピングを把握し、それに応じてのため –

+0

感謝を@JsonIgnoreを追加する必要があります。ちょうどあなたのコントローラーを変更を修正するために

高速返信! 私が行う場合、私はmeasurementListを使用することができません、そうですか?私はこの要望を必要とするので、@JsonIgnoreを使用することはできません –

+0

次にmeasurementListマッピングで@JsonIgnoreを使用してください –

1

それが起こる:あなたのJSONは、これを避ける@JsonIgnoreアノテーションを使用して、ループに入っているので、

+0

Maksym、読んでくれてありがとう、本当に良いアイデアです。これらのリストが必要なので、@JsonIgonreマッピングオブジェクト内のTrashCanとTrashSensorの内部 申し訳ありませんが、DTOがどのように私を助けてくれるのか分かりません...このコントローラーの穴の目的は、DBからデータを取得することです。POJOから直接取得することは、この状況では本当にうまく見えます。とにかく、フレームワークはほとんどすべてをやっています。 あなたはどう思いますか? –

+0

@LeandroBorgesFerreira、DTOはベストプラクティスとみなされます。 POJOのシリアライズは悪いコードです。あなたのケースでは、あなたのアプリケーションがそれほど大きくなく、それ以上大きくならない場合は、それらを直列化することができます。しかし、検証を追加したい場合や、完全ではないエンティティを他の場所に提供することに決めた場合は、アプリケーションの任意の場所でシリアル化を変更する必要があります。すべてのリレーションを持つ完全なエンティティを残して、コントローラなどのために特別なDTOを作成してシリアル化するだけです。また、大きなアプリケーションでモデルをよりクリーンにすることができます。 –

0

について読むことができます。

デシリアライズ中に休止状態のレイジーローディングとセッションがないため、この例外が発生しています。

@RequestMapping(value="/trashCan", method=RequestMethod.GET) 
    public ResponseEntity<Iterable<TrashCan>> getPlaces(){ 
     Iterable<TrashCan> trashCanIterable = trashCansRepository.findAll(); 
     List<TrashCan> responseList = new ArrayList<TrashCan>(trashCanIterable.size()) 
     while(trashCanIterable.hasNext()){ 
      TrashCan trashCan = trashCanIterable.next(); 
      for(TrashMeter trashMeter : trashCan.trashMeterList){ 

      } 
      for(TrashSensor trashSensor : trashCan.trashSensorList){ 

      } 
      responseList.add(trashCan); 
     } 
     return new ResponseEntity<>(responseList, HttpStatus.OK); 
    } 
関連する問題