如何解决Spring JPA-保留@ManyToMany实体-重复的实体错误
我的用例需要帮助。
我有一个Order
实体
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToMany(cascade = {
CascadeType.PERSIST,CascadeType.MERGE
})
@JoinTable(name = "inconsistent_orders",joinColumns = @JoinColumn(name = "order_id"),inverseJoinColumns = @JoinColumn(name = "inconsistency_id")
)
private Set<OrderInconsistency> inconsistencies;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Set<OrderInconsistency> getInconsistencies() {
return inconsistencies;
}
//getters and setters ommitted for brevity
public void setInconsistencies(Set<OrderInconsistency> inconsistencies) {
this.inconsistencies = inconsistencies;
this.inconsistencies.forEach(i -> i.setOrders(List.of(this)));
}
//hashcode and equals ommitted for brevity
}
和一个OrderInconsistency
实体
@Entity
@Table(name = "order_inconsistencies")
public class OrderInconsistency {
@Id
@Column(name = "id")
private String id;
@Basic
@Column(name = "description")
private String description;
@ManyToMany(mappedBy = "inconsistencies")
private List<Order> orders = new ArrayList<>();
public OrderInconsistency() {
}
public OrderInconsistency(String id,String description) {
Assert.notNull(id,"El id de la inconsistencia no puede ser null");
this.id = id.replaceAll(" ","_").toUpperCase();
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OrderInconsistency that = (OrderInconsistency) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
}
我的多对多表格:
CREATE TABLE `inconsistent_orders`
(
`order_id` INT(11) NOT NULL,`inconsistency_id` VARCHAR(25) NOT NULL,PRIMARY KEY (`order_id`,`inconsistency_id`),FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,FOREIGN KEY (`inconsistency_id`) REFERENCES `order_inconsistencies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB;
这个想法是Order
是这种关系的父级,因此当我保存Order
时,它应该保存其不一致之处(如果有)。
订单不一致一旦创建就不会改变。例如,如果保存了一个新的Order
并且它的ID为OrderInconsistency
的{{1}},并且不存在与该ID不一致的地方,那么JPA应该先创建一个新ID,然后再保存顺序,然后按该顺序将其添加到TOTALS_DONT_MATCH
不一致的地方。
将来,其他订单可能会存在这种不一致的情况,并且由于它已经存在于数据库中,因此JPA不应创建它,而只是将其添加到多对多表Set
中。
但是,我面临的问题是,即使我手动将一个已经存在的ID分配给手动创建的inconsistent_orders
实例,JPA也会尝试插入它,从而导致重复的输入错误
总而言之,我第一次保存订单时,它可以工作并且OrderInconsistency
被保存。如果另一个OrderInconsistency
被保存并且具有相同的Order
,即使它已经存在并且失败,JPA也会尝试插入它。。
例如
OrderInconsistency
我想出的解决方案是拥有一个@Transactional
public ValidatedOrderDTO saveConsistentOrder(Order order) {
boolean consistentOrder = true;
var orderInconsistencies = new HashSet<OrderInconsistency>();
for (OrderValidationService validationService : orderValidationServices) {
ValidationResult validationResult = validationService.validate(order);
if (!validationResult.isValid()) {
// this returns a manually created instance of OrderConsistency with an ID that already exists in the DB
OrderInconsistency inconsistency = validationResult.getOrderInconsistency();
orderInconsistencies.add(inconsistency);
consistentOrder = false;
}
}
order.setInconsistencies(orderInconsistencies);
ordersDAO.save(order); //here,JPA attempts to INSERT the OrderInconsistency even though it already exists in DB
return new ValidatedOrderDTO(consistentOrder,consistenciesDescription);
}
并手动OrderInconsistencyDAO
不一致,如果存在,请将其添加到findById
中,如果不存在,则将新实例分配给Order
。我不明白为什么这样做有效,以及这样做是否正确。它与托管和非托管实体有关吗?
工作示例-我不明白为什么会这样
Order
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。