ObjectMapper.writeValueAsString JsonMappingException:延迟初始化失败
ObjectMapper.writeValueAsString JsonMappingException: failed to lazily initialize
有两个问题我不明白。
首先,控制台上的错误消息。它没有给我完整的错误信息。因此我根本不明白这个问题 :S IDE 是 STS。
其次,为什么会出现这个错误,"JsonMapping failed to lazily initialize a..."
@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: failed to lazily
initialize a collection of role:
me.eraytuncer.carpool.entity.User.carList, could not initialize proxy
- no Session (through reference chain: me.eraytuncer.carpool.entity.Car["owner"]->me.eraytuncer.carpool.entity.User["carList"])
更新二:
@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);
}
}
更新四:
添加@JsonIgnore 以某种方式解决了这个问题。可能是无限递归引起的误导问题?
您已将 @OneToOne
映射到 @OneToMany
。拥有方应该是@ManyToOne
:
@ManyToOne
@JoinColumn(name = "user_id") // if needed
private User owner;
我遇到了同样的问题,通过在方法上使用 @Transactional
解决了这个问题。 @Transactional
帮助保持会话打开,以便可以获取惰性集合。
看起来像字段
private List<Car> carList;
延迟解析(@OneToMany
中的默认提取类型),这意味着它仅在调用此字段的 getter 时从数据库填充。在您的情况下,它由 Hibernate 会话范围之外的 Jackson 序列化程序调用,并且 属性 无法填充。在 @OneToMany
on carList
属性 中将 fetch
类型更改为 EAGER 应该会有所帮助。
也考虑使用 DTO 模式,因为从 API 返回实体被认为是不好的做法。
有两个问题我不明白。 首先,控制台上的错误消息。它没有给我完整的错误信息。因此我根本不明白这个问题 :S IDE 是 STS。
其次,为什么会出现这个错误,"JsonMapping failed to lazily initialize a..."
@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: failed to lazily initialize a collection of role: me.eraytuncer.carpool.entity.User.carList, could not initialize proxy - no Session (through reference chain: me.eraytuncer.carpool.entity.Car["owner"]->me.eraytuncer.carpool.entity.User["carList"])
更新二:
@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);
}
}
更新四:
添加@JsonIgnore 以某种方式解决了这个问题。可能是无限递归引起的误导问题?
您已将 @OneToOne
映射到 @OneToMany
。拥有方应该是@ManyToOne
:
@ManyToOne
@JoinColumn(name = "user_id") // if needed
private User owner;
我遇到了同样的问题,通过在方法上使用 @Transactional
解决了这个问题。 @Transactional
帮助保持会话打开,以便可以获取惰性集合。
看起来像字段
private List<Car> carList;
延迟解析(@OneToMany
中的默认提取类型),这意味着它仅在调用此字段的 getter 时从数据库填充。在您的情况下,它由 Hibernate 会话范围之外的 Jackson 序列化程序调用,并且 属性 无法填充。在 @OneToMany
on carList
属性 中将 fetch
类型更改为 EAGER 应该会有所帮助。
也考虑使用 DTO 模式,因为从 API 返回实体被认为是不好的做法。