我正在尝试创建一个接受“食物”项目并保存它的 post 方法。食品实体有两个外国字段,称为“餐厅”和“菜单”。当我发送请求时,由于某种原因,Spring boot 尝试从菜单对象访问餐厅的 id 字段。我该如何修复这个错误?
这是我的实体。
@Entity
@Getter
@Setter
@NoArgsConstructor
@JsonSerialize(using = MenuSerializer.class)
public class Menu {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id", nullable = false)
@JsonIgnore
private Restaruant restaurant;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "menu_id")
private List<Food> foods = new ArrayList<Food>();
@Override
public String toString() {
return "Menu [id=" + id + ", name=" + name + ", restaurant=" + restaurant + ", foods=" + foods + "]";
}
}
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Food {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY)
private Long Id;
private String name;
private String picture;
private Double price;
@Column(columnDefinition = "text")
private String description;
private String category;
private Double discount;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "menu_id", nullable = false)
@JsonIncludeProperties({"id"})
private Menu menu;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id", nullable = false)
@JsonIncludeProperties({"id"})
private Restaruant restaurant;
@OneToMany(mappedBy = "food")
@JsonIgnore
private List<CartItem> cartItems = new ArrayList<>();
private Boolean available;
@Override
public String toString() {
return "Food [Id=" + Id + ", name=" + name + ", picture=" + picture + ", price=" + price + ", description="
+ description + ", category=" + category + ", discount=" + discount + ", menu=" + menu + ", restaurant="
+ restaurant + ", cartItems=" + cartItems + ", available=" + available + "]";
}
}
@Entity
@Setter
@Getter
@NoArgsConstructor
public class Restaruant {
@Id
@GeneratedValue ( strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String profile;
private Boolean available;
@Column(columnDefinition = "text")
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "owner_id")
@JsonIgnore
private User owner;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "address_id", referencedColumnName = "id")
@JsonIgnore
private Address address;
@ManyToOne
@JoinColumn(name = "region_id")
@JsonIgnore
private Region region;
}
这是我的控制器方法。这里没有什么特别的。
@PostMapping("/create")
public ResponseEntity<Food> createFood(@RequestBody Food food, Principal principal) {
//restaurantService.validateRestaurantOwner(food.getRestaurant().getId(), principal.getName());
System.out.println(food);
Food createdFood = foodService.saveFood(food);
return ResponseEntity.status(HttpStatus.CREATED).body(createdFood);
}
我在保存之前打印了食物对象,以便我可以看到它是什么样子。
Food [Id=null, name=jkla;f, picture=null, price=10.0, description=ffff, category=jfla, discount=1.0, menu=Menu [id=3, name=null, restaurant=null, foods=[]], restaurant=com.hostmdy.food.domain.Restaruant@4c91c71a, cartItems=[], available=true]
这个物体正是我所期望的。不知道是不是有什么问题。 这是我收到的错误消息。
[2m2024-09-10T18:01:34.590+06:30[0;39m [33m WARN[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot invoke "com.hostmdy.food.domain.Restaruant.getId()" because the return value of "com.hostmdy.food.domain.Menu.getRestaurant()" is null]
Spring 正在尝试访问 Menu.getRestaurant()。它不应该这样做。
我还打印了所有调试行,以防你们想看。
Executing identity-insert immediately
[2m2024-09-10T18:01:34.546+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.SQL [0;39m [2m:[0;39m insert into food (available,category,description,discount,menu_id,name,picture,price,restaurant_id,id) values (?,?,?,?,?,?,?,?,?,default)
[2m2024-09-10T18:01:34.548+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.orm.results [0;39m [2m:[0;39m Initializer list is empty
[2m2024-09-10T18:01:34.548+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.orm.results.loading [0;39m [2m:[0;39m Calling top-level assembler (0 / 1) : org.hibernate.sql.results.graph.basic.BasicResultAssembler@7d41471c
[2m2024-09-10T18:01:34.548+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36morg.hibernate.orm.results [0;39m [2m:[0;39m Extracted JDBC value [0] - [7]
[2m2024-09-10T18:01:34.551+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.id.IdentifierGeneratorHelper [0;39m [2m:[0;39m Extracted generated values [com.hostmdy.food.domain.Food]: [Ljava.lang.Object;@643eaf3f
[2m2024-09-10T18:01:34.554+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.orm.jpa.JpaTransactionManager [0;39m [2m:[0;39m Initiating transaction commit
[2m2024-09-10T18:01:34.555+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.orm.jpa.JpaTransactionManager [0;39m [2m:[0;39m Committing JPA transaction on EntityManager [SessionImpl(610926081<open>)]
[2m2024-09-10T18:01:34.555+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.t.internal.TransactionImpl [0;39m [2m:[0;39m committing
[2m2024-09-10T18:01:34.555+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener [0;39m [2m:[0;39m Processing flush-time cascades
[2m2024-09-10T18:01:34.556+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener [0;39m [2m:[0;39m Dirty checking collections
[2m2024-09-10T18:01:34.557+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.hibernate.engine.internal.Collections [0;39m [2m:[0;39m Collection found: [com.hostmdy.food.domain.Food.cartItems#7], was: [<unreferenced>] (initialized)
[2m2024-09-10T18:01:34.558+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener [0;39m [2m:[0;39m Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
[2m2024-09-10T18:01:34.558+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.h.e.i.AbstractFlushingEventListener [0;39m [2m:[0;39m Flushed: 1 (re)creations, 0 updates, 0 removals to 1 collections
[2m2024-09-10T18:01:34.565+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.hibernate.internal.util.EntityPrinter [0;39m [2m:[0;39m Listing entities:
[2m2024-09-10T18:01:34.567+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.hibernate.internal.util.EntityPrinter [0;39m [2m:[0;39m com.hostmdy.food.domain.Food{price=10.0, restaurant=com.hostmdy.food.domain.Restaruant#1, available=true, name=jkla;f, description=ffff, discount=1.0, Id=7, cartItems=[], category=jfla, menu=com.hostmdy.food.domain.Menu#3, picture=null}
[2m2024-09-10T18:01:34.568+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.orm.jpa.JpaTransactionManager [0;39m [2m:[0;39m Not closing pre-bound JPA EntityManager after transaction
[2m2024-09-10T18:01:34.579+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.w.s.m.m.a.HttpEntityMethodProcessor [0;39m [2m:[0;39m Using 'application/json', given [*/*] and supported [application/json, application/*+json]
[2m2024-09-10T18:01:34.580+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.w.s.m.m.a.HttpEntityMethodProcessor [0;39m [2m:[0;39m Writing [Food [Id=7, name=jkla;f, picture=null, price=10.0, description=ffff, category=jfla, discount=1.0, me (truncated)...]
[2m2024-09-10T18:01:34.590+06:30[0;39m [33m WARN[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36m.w.s.m.s.DefaultHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot invoke "com.hostmdy.food.domain.Restaruant.getId()" because the return value of "com.hostmdy.food.domain.Menu.getRestaurant()" is null]
[2m2024-09-10T18:01:34.590+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.j.s.OpenEntityManagerInViewInterceptor[0;39m [2m:[0;39m Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
[2m2024-09-10T18:01:34.593+06:30[0;39m [32mDEBUG[0;39m [35m9736[0;39m [2m---[0;39m [2m[food_delivery_api] [nio-8686-exec-1][0;39m [2m[0;39m[36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Completed 500 INTERNAL_SERVER_ERROR
我还尝试创建自定义解串器,但它仍然不起作用。
问题来自
@JsonIncludeProperties({"id"})
。因此它会尝试序列化该属性。
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "restaurant_id", nullable = false)
@JsonIncludeProperties({"id"}) //this
private Restaruant restaurant;
您可以通过从
Food
中删除这些注释来修复它。如果另一个控制器依赖于此,我建议您使用 @JsonView
根据上下文进行不同的序列化。