我随机获得以下异常:org.eclipse.persistence.exceptions.ValidationException Exception Description: The attribute [id] of class [domain.Person] is mapped to a primary key column in the database. Updates are not allowed.
执行“deleteAllPersons()”时会抛出异常。当两个实体之间存在必须删除的链接时,会出现错误,并且似乎发生在我的案例中被删除的第二个人身上。
同样值得注意的是,错误通常不会出现在调试模式中,也不会出现在测试套件上运行的情况。这使我相信问题可能与时间有关,或者原因是不一致的,在某些情况下会在导致任何问题之前自动解决。
public void deleteAllPersons(){
for(Person person: getAllPersons()){
long id = person.getId();
deletePerson(id);
}
使用deletePerson(id)方法
public void deletePerson(long id) {
Person person = getPerson(id);
List<OrderBill> ordersToBeUnlinked = new ArrayList<>();
ordersToBeUnlinked.addAll(person.getOrders());
for (OrderBill order : ordersToBeUnlinked) {
person.removeOrder(order);
System.out.println(order + "deleted");
}
try{
manager.getTransaction().begin();
manager.merge(person);
} catch (Exception e1){
throw new DbException("Error merging person" + person + "\n" + e1.getMessage(), e1);
}
try {
manager.remove(person);
manager.flush();
manager.getTransaction().commit();
} catch (Exception e){
manager.getTransaction().rollback();
throw new DbException("error deleting " + person + "\n" + e.getMessage(), e);
}
}
合并很顺利,但在删除时会抛出异常。 在异常消息中,我可以看到Person在列表中没有更多订单
如果我在Person或OrderBill类中犯了错误, 以下是这两个类中最重要的部分:
人
@Entity(name="Person")
public class Person {
@Id
@Column(name="PERSON_ID")
@GeneratedValue
private long id;
@ManyToMany(mappedBy="authors", fetch=FetchType.LAZY, cascade={CascadeType.MERGE})
private Set<OrderBill> orders;
@Column(name="name")
private String name = "undefined";
public Person(String name){
setName(name);
payments = new HashSet<Payment>();
orders = new HashSet<OrderBill>();
}
public void removeOrder(OrderBill order){
orders.remove(order);
if(order.getAuthors().contains(this)){
order.removeAuthor(this);
}
}
OrderBill:
@Entity(name="OrderBill")
@NamedQueries({
@NamedQuery(name="Order.getAll", query="select o from OrderBill o"),
@NamedQuery(name="Order.findOrders", query="select o from OrderBill o join o.orderWeek as w where (w.weekNr = :w and w.yearNr = :y)")
})
public class OrderBill implements Transaction{
@Id
@Basic(optional = false)
@NotNull
@Column(name="ORDER_ID")
@GeneratedValue
private long id;
@ManyToMany
@JoinTable(
name="ORDER_PERSON",
joinColumns=@JoinColumn(name="ORDER_ID"),
inverseJoinColumns=@JoinColumn(name="PERSON_ID")
)
private Set<Person> authors;
public OrderBill(double totalCost, int weekNr, int yearNr){
setOrderWeek(new OrderWeek(weekNr, yearNr));
setTotalCost(totalCost);
authors = new HashSet<>();
}
public void removeAuthor(Person author){
authors.remove(author);
if(author.getOrders().contains(this))
author.removeOrder(this);
}
答案 0 :(得分:0)
如果它可以帮助某人,我会写下我在下面找到的内容:
克里斯的评论结果证明是正确的,但是在我发现我在尝试删除所有引用时出错的时候花了很长时间。
我不知道这是否是唯一的问题,但我发现了一个主要的逻辑缺陷:
但订单列表标记为“mappedBy”,因此其更改不会反映在数据库中
但是通过更新此人,带有订单的列表将被清空。因此,当合并人员时不会留下对更新订单的引用(因此级联合并不会影响他们)
我通过在deletePerson
中的for循环中添加merge(order)来解决问题for (OrderBill order : ordersToBeUnlinked) {
person.removeOrder(order);
manager.merge(order);
}
注意:当然,由于合并,我不得不将此for循环放在事务中。