spring boot - 如何将多对一实体保存到数据库
spring boot - how to save many-to-one entities to database
在this spring boot app中,我有一个从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": []
}
]
然而,当我想将 Item
添加到现有的 Cart
时,新的 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;
}
假设我想将名称为 "beer" 的 Item
添加到名称为 cartid=1
的 Cart
。在我看来,我只需要 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
应该从哪里得到 cartid
Item
忽略任何 Cart
信息!如果我 POST
什么也不起作用
{
"itemName":"beer",
"cart":{
"id":1,
"items":[]
}
}
这也将新项目保存为空。
我真正想要避免的是切换JsonBackReference
和JsonManagedReference
。
我怎样才能将 Item
添加到 Cart
?
这是实体类
@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;
/*..*/
}
感谢您的帮助
P.S.: 如果你想克隆开头链接的 repo,你还需要 运行 eureka server and clone the 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;
/*..*/
}
现在我可以快乐地POST Item
{
"itemName":"beer",
"cartid":1
}
在this spring boot app中,我有一个从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": []
}
]
然而,当我想将 Item
添加到现有的 Cart
时,新的 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;
}
假设我想将名称为 "beer" 的 Item
添加到名称为 cartid=1
的 Cart
。在我看来,我只需要 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
应该从哪里得到 cartid
Item
忽略任何 Cart
信息!如果我 POST
{
"itemName":"beer",
"cart":{
"id":1,
"items":[]
}
}
这也将新项目保存为空。
我真正想要避免的是切换JsonBackReference
和JsonManagedReference
。
我怎样才能将 Item
添加到 Cart
?
这是实体类
@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;
/*..*/
}
感谢您的帮助
P.S.: 如果你想克隆开头链接的 repo,你还需要 运行 eureka server and clone the 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;
/*..*/
}
现在我可以快乐地POST Item
{
"itemName":"beer",
"cartid":1
}