在这个春季启动应用程序中,我有一个从Cart
到Item
的one-to-many
映射,其中序列化周期是通过忽略Item
的序列化中的Cart
来解决的。 (因此,Item
中的Cart
字段带有@JsonBackReference
公告)
Spring 引导成功初始化数据库,以便 GET-ing 所有Cart
s 给出 json
[
{
"id": 1, <-- cart 1
"items": [
{
"id": 0, <-- item 0
"itemName": "tooth brush"
},
{
"id": 1,
"itemName": "shampoo"
}
]
},
{
"id": 2,
"items": [
{
"id": 2,
"itemName": "body wash"
}
]
},
{
"id": 3,
"items": []
}
]
但是,当我想向现有Cart
添加Item
时,新Item
将另存为null
@PostMapping("carts/{cartId}")
public Cart addItemToCart(@PathVariable("cartId") long cartId, @RequestBody Item item)
{
LOG.info("Trying to add ITEM: id={}, name={}, cart={} to CART: {}", item.getId(), item.getItemName(), item.getCart(), cartId);
Cart cart = dao.getById(cartId);
LOG.info("I) CART: id={}, items={}", cart.getId(),cart.getItems().stream().map(i -> i.getItemName()).collect(Collectors.toList()));
// also tried at this location: item.setCart(cart);
cart.getItems().add(item);
LOG.info("II) CART: id={}, items={}", cart.getId(),cart.getItems().stream().map(i -> i.getItemName()).collect(Collectors.toList()));
Cart res = dao.save(cart); // HERE CART SAVES NEW ITEM AS NULL
LOG.info("III) CART: id={}, items={}", res.getId(),res.getItems().stream().map(i -> i.getItemName()).collect(Collectors.toList()));
Cart resCheck = dao.getById(res.getId());
LOG.info("IV) CART: id={}, items={}", resCheck.getId(),resCheck.getItems().stream().map(i -> i.getItemName()).collect(Collectors.toList()));
return res;
}
假设我想添加一个名称为"啤酒"的Item
,以Cart
cartid=1
。在我看来,我只需要 json 中的itemName
,因为Cart
字段被忽略(@JsonBackReference
),并且itemid
是自动生成的。
所以,发布
{
"itemName":"beer"
}
localhost:9200/demo/api/carts/1
给出日志(与上面的代码比较)
Trying to add ITEM: id=0, name=beer, cart=null to CART: 1
I) CART: id=1, items=[tooth brush, shampoo]
II) CART: id=1, items=[tooth brush, beer, shampoo]
III) CART: id=1, items=[null, tooth brush, shampoo] <-- beer itemName is null after dao.save()
IV) CART: id=1, items=[null, tooth brush, shampoo]
这并不奇怪,因为Cart
s 和Item
s 都连接在一起cartid
但是当序列化Item
忽略任何Cart
信息时,啤酒Item
应该从哪里获得cartid
!如果我发布什么也不起作用
{
"itemName":"beer",
"cart":{
"id":1,
"items":[]
}
}
这也将新项目保存为 null。
我真正想避免的是切换JsonBackReference
和JsonManagedReference
。
如何仍可将Item
s 添加到Cart
s?
以下是实体类
@Entity
@Table(name="items")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Item
{
@Id
@GenericGenerator(name="itemIdGen" , strategy="increment")
@GeneratedValue(generator="itemIdGen")
@Column(name = "itemid", nullable=false)
private long id;
@Column(name="itemname")
private String itemName;
@ManyToOne
@JoinColumn(name = "cartid", nullable=false)
@JsonBackReference
private Cart cart;
/*...*/
}
@Entity
@Table(name="carts")
public class Cart
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "cartid", nullable=false)
private long id;
@Column(name="items")
@OneToMany(mappedBy = "cart")
@JsonManagedReference
private Set<Item> items;
/*..*/
}
感谢您的帮助
PS:如果你想克隆一开始链接的仓库,你还需要运行尤里卡服务器并克隆demo-commons项目。
> 解决方案是忘记在Item
中引用整个Cart
对象,而只保留cartid
(合并)
@Entity
@Table(name="carts")
public class Cart
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "cartid", nullable=false)
private long id;
// @Column(name="items")
// @OneToMany(mappedBy = "cart")
// @JsonManagedReference
// private Set<Item> items;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="cartid", referencedColumnName="cartid")
private Set<Item> items;
/*..*/
}
@Entity
@Table(name="items")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Item
{
@Id
@GenericGenerator(name="itemIdGen" , strategy="increment")
@GeneratedValue(generator="itemIdGen")
@Column(name = "itemid", nullable=false)
private long id;
@Column(name="itemname")
private String itemName;
// @ManyToOne
// @JoinColumn(name = "cartid", nullable=false)
// @JsonBackReference
// private Cart cart;
@Column(name="cartid")
private Long cartId;
/*..*/
}
现在我可以愉快地发布Item
{
"itemName":"beer",
"cartid":1
}