Уникальное нарушение ограничения с упорядоченным списком Hibernate - PullRequest
1 голос
/ 08 января 2012

У меня есть следующие объекты, и я получаю исключение, если я пытаюсь удалить Task из TaskList с помощью removeTask метода.

@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?

UPDATE

Кажется, это проблема гибернации. Нечто с порядком delete и update операторов. Следующий взлом решил проблему (частично):

@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 - очистка коллекции с помощью all-delete-orphan и последующее добавление к ней приводит к возникновению ConstraintViolationException , ведущему my в правильном направлении.

Но orphanRemoval=true не работает с моим обходным путем. Это приводит к следующему исключению: «Коллекция с cascade =« all-delete-orphan »больше не упоминалась экземпляром объекта-владельца». Так что проблема на самом деле не решена.

1 Ответ

1 голос
/ 08 января 2012

Ваша двунаправленная связь отображается дважды: один раз в 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 проверяет, чтобы знать, что связь должна быть удалена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...