【问题标题】:Unique constraint violation with ordered Hibernate list具有有序 Hibernate 列表的唯一约束违规
【发布时间】:2012-01-07 21:37:53
【问题描述】:

如果我尝试通过removeTask 方法从TaskList 中删除Task,我有以下实体并出现异常。

@Entity
public class TaskList extends GenericModel {

  @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
  @OrderColumn(name="position", nullable=false)
  public List<Task> tasks = new ArrayList<>();

  // ...

  public void removeTask(Task task) {
    tasks.remove(task);
  }
}

@Entity
public class Task extends Model {

  @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
  @JoinColumn(name="task_id")
  private List<Reservation> reservations = new ArrayList<>();

  @ManyToOne
  public TaskList taskList;

  // ...
}

@Entity
public class Reservation extends GenericModel {

  @Id
  private String id = Token.generate(8);

  @ManyToOne
  private Task task;

  // ...
}

例外是:

"CONSTRAINT_INDEX_F ON PUBLIC.TASKLIST_TASK(TASKS_ID)"
Unique index or primary key violation: "CONSTRAINT_INDEX_F ON PUBLIC.TASKLIST_TASK(TASKS_ID)"; SQL statement:
update TaskList_Task set tasks_id=? where TaskList_id=? and position=? [23001-149]

我将 JPA 2 与 Hibernate 3.6.1 一起使用。我的映射有问题还是 Hibernate 错误?

更新

这似乎是一个休眠问题。 deleteupdate 语句的顺序。以下 hack 解决了问题(部分):

@Entity
public class TaskList extends GenericModel {

  // ....

  public void removeTask(Task task) {
    tasks.remove(task);
    tasks = new ArrayList<>(tasks); // only for Hibernate
    task.taskList = null;
  }
}

Hibernate - clearing a collection with all-delete-orphan and then adding to it causes ConstraintViolationException 带领我走向正确的方向。

但是 orphanRemoval=true 不适用于我的解决方法。它导致下一个异常:“拥有的实体实例不再引用具有 cascade="all-delete-orphan" 的集合”。所以问题并没有真正解决。

【问题讨论】:

  • 太好了,黑客对我有用!我的场景如下:我从列表中删除了第一个元素,然后将元素附加到列表的末尾。

标签: java hibernate jpa unique-constraint


【解决方案1】:

您的双向关联被映射了两次:一次在 TaskList 中,一次在 Task 中。 TaskList 中的映射注解应该是

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="task") 
@OrderColumn(name="position", nullable=false)
public List<Task> tasks = new ArrayList<>();

如果没有 mappedBy 属性,Hibernate 会认为您有两个独立的关联(我怀疑这就是您想要的),而不是双向关联。

此外,当您修改双向关联时,关联的双方都应该修改。所以removeTask方法应该是

public void removeTask(Task task) {
    tasks.remove(task);
    task.setTaskList(null);
}

这尤其重要,因为关联的拥有方是Task(因为那里没有mappedBy 属性)。所以这就是 Hibernate 检查知道必须删除关联的一面。

【讨论】:

  • mappedBy 不能与@OrderColumn 一起使用,因为 Hibernate 认为这是一种不好的做法,需要一个连接表来代替。请参阅:stackoverflow.com/questions/2956171 我尝试按照建议删除引用,但没有解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 2022-01-23
  • 2018-01-10
  • 2012-10-18
  • 1970-01-01
相关资源
最近更新 更多