在我的应用程序中,用户下订单并将账单地址设置为与他映射的地址之一。现在,他将来会编辑该地址。因此我的订单将映射到该更新的地址。
我的订单实体
@Entity
public class Orders{
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@OneToOne
private Address address;
...
}
地址实体
@Entity
@Table(name = "address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String address1;
...
}
人员实体
@Entity
public class Person{
...
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Address> addresses = new HashSet<>();
...
}
我希望我的Order实体拥有创建订单时的地址副本。创建订单后,用户在其个人资料中对Address的任何更改都不会对该订单产生影响。
答案 0 :(得分:1)
我假设您允许用户从他的地址列表中选择地址(人#地址),因此,当您提交订单时,它包含数据库中已经存在的地址,包括创建关系的id
,不会创建记录:
{
user: {
id: 10,
email: "user@stackoverflow.com"
},
address: {
id: 10,
street: "5th Av"
}
}
如果您想“ 拥有地址副本”,则应首先在Order
类中更新您的关系,例如:
@OneToOne(cascade = CascadeType.ALL)
private Address address;
然后发送不带id
的地址,这表明您的存储库将在数据库中创建一个新条目。
Json选项:
{
user: {
id: 10,
email: "user@stackoverflow.com"
},
address: {
street: "5th Av", ...
}
}
或通过删除控制器上的id
:
@PostMapping("/submit-order")
public Order submitOrder( @RequestBody Order order) {
// Remove Order#id to detatch current record and enforce create a new one
order.getAddress().setId(null);
return this.orderRepository.save(order);
}
通过这种方式,您的订单具有唯一的地址副本。
错误:消息为“地址已从1更改为空”的org.springframework.orm.jpa.JpaSystemException
如果收到此错误,是因为要在事务或会话范围内删除实体的ID。您应该在该范围之外创建实体的副本,或者使用实体管理器来分离实体,这里是example。
@嵌入式解决方案
另一种解决方案是改为使用可嵌入对象,这样您可以将地址字段存储在订单表上,但可以将它们作为复合对象:
首先,创建一个包含所有必填字段的订单地址对象,并用@Embeddable
批注对其进行标记:
@Embeddable
public class AddressOrder {
@Column("street")
private String street;
@Column("postal_code")
private String po;
@Column("city")
private String city;
@Column("country")
private String country;
// Getters and setters
}
然后,将订单表上的对象用作属性,并用@Embedded
批注对其进行标记。
@Entity
public class Orders {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Embedded
private AddressOrder address;
// Getters and setters
}
您需要根据要使用的数据库方法选择解决方案。