从Hibernate反序列化JSON

时间:2016-11-04 12:35:25

标签: java json spring hibernate jackson

我遇到了在Spring Boot中反序列化类的问题。当我的控制器试图反序列化它时,它崩溃了。这是班级:

@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() {
    }

}

我的控制器:

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

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

当我调用webservice时,我收到此错误:

  

无法写入HTTP消息:org.springframework.http.converter.HttpMessageNotWritableException:无法写入内容:无法反序列化(通过引用链:java.util.ArrayList [0] -br.com.simplepass.cleanerway.domain .TrashCan [&#34; trashSensorList&#34;] - org.hibernate.collection.internal.PersistentBag [0] -br.com.simplepass.cleanerway.domain.TrashSensor [&#34; measurementList&#34;]);嵌套异常是com.fasterxml.jackson.databind.JsonMappingException:无法反序列化(通过引用链:java.util.ArrayList [0] -br.com.simplepass.cleanerway.domain.TrashCan [&#34; trashSensorList&#34; ] -org.hibernate.collection.internal.PersistentBag [0] -br.com.simplepass.cleanerway.domain.TrashSensor [&#34; measurementList&#34;])

我无法解释此错误=/。对此问题的任何帮助都非常感谢。

3 个答案:

答案 0 :(得分:1)

由于你的json进入循环,你收到此错误,为避免这种情况,请使用@JsonIgnore注释:

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

答案 1 :(得分:1)

当您使用实体之间的关系时会发生这种情况。想象一下,您的TrashCan已链接到垃圾桶。你的垃圾桶里有它的包装纸 - 垃圾桶。那么你试图序列化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(数据传输对象)模式进行序列化/反序列化。它还为您提供更大的灵活性。你可以阅读它{{3}}

答案 2 :(得分:0)

如果您需要 trashMeterList trashSensorList 作为回应,请按照此回答。

由于hibernate延迟加载而反序列化时没有会话,因此您将获得此异常。

要修复只需更改控制器:

    @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);
    }