ObjectMapper.writeValueAsString JsonMappingException:无法延迟初始化

时间:2019-08-09 12:31:21

标签: json spring-boot jpa spring-test objectmapper

有两个我不明白的问题。 首先,控制台上的错误消息。它没有给我完整的错误信息。因此,我根本不理解问题:S IDE是STS。

enter image description here

第二,为什么出现此错误,“ JsonMapping无法延迟初始化...”

@Test
public void testUpdateCar() throws Exception {
    Car car = carRepository.findById(new Long(1)).get();
    car.setBrand("Mazda");
    car.setModel("326");

    String putJSON = objectMapper.writeValueAsString(car);
    mockMVC.perform(MockMvcRequestBuilders.put(String.format("/api/cars/%d", car.getId())).contentType(MediaType.APPLICATION_JSON_UTF8).content(putJSON))
    .andDo(MockMvcResultHandlers.print())
    .andExpect(MockMvcResultMatchers.status().isCreated())
    .andExpect(MockMvcResultMatchers.content().contentType("application/hal+json;charset=UTF-8"));
}

汽车:

@Entity
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @OneToOne
    private User owner;
    private String brand;
    private String model;
    private String color;
    private String plate;
    private String additionals;

更新1: 错误本身:

  

com.fasterxml.jackson.databind.JsonMappingException:懒惰地失败   初始化角色集合:   me.eraytuncer.carpool.entity.User.carList,无法初始化代理   -没有会话(通过参考链:me.eraytuncer.carpool.entity.Car [“所有者”]-> me.eraytuncer.carpool.entity.User [“ carList”])

更新2:

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private String phone;
    private String email;

    @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "owner")
    private List<Car> carList;

更新3:

@PutMapping("/cars/{id}")
ResponseEntity<?> replaceCar(@RequestBody Car newCar, @PathVariable Long id) {
    if (repository.existsById(id)) {
        newCar.setId(id);
        Resource<Car> carResource = assembler.toResource(repository.save(newCar));
        try {
            return ResponseEntity
                    .created(new URI(carResource.getId().expand().getHref()))
                    .body(carResource);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }                   
    } else {
        throw new CarNotFoundException(id);
    }
}

更新4:

添加@JsonIgnore以某种方式解决了该问题。也许是无限递归引起的误导性问题?

3 个答案:

答案 0 :(得分:1)

看起来像字段

private List<Car> carList;

是延迟解析的({{1}中的默认提取类型),这意味着只有在调用此字段的getter时才从DB填充它。在您的情况下,Jackson序列化程序在Hibernate会话范围之外调用该方法,并且无法填充属性。在@OneToMany属性的fetch中将@OneToMany类型更改为EAGER应该会有所帮助。

还考虑使用DTO模式,因为从API返回实体被认为是不好的做法。

答案 1 :(得分:0)

您已将@OneToOne映射到@OneToMany。拥有方应为@ManyToOne

    @ManyToOne
    @JoinColumn(name = "user_id") // if needed
    private User owner;

答案 2 :(得分:0)

我也遇到了同样的问题,方法上使用@Transactional解决了这个问题。 @Transactional帮助保持会话打开状态,以便可以获取懒惰的集合。