Hibernate и NonUniqueObjectException - PullRequest
       4

Hibernate и NonUniqueObjectException

5 голосов
/ 23 августа 2010

У меня есть объект, который содержит два других объекта с отношением @ManyToOne.

@Entity
public class A extends Serializable{

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @Cascade(CascadeType.SAVE_UPDATE)
    private B b;

    @ManyToOne
    @Cascade(CascadeType.SAVE_UPDATE)
    private C c;

}

Если я пытаюсь сохранить экземпляр A, имеющий "B_ID" и "C_ID" другой записи A, я получаю исключение:

org.hibernate.NonUniqueObjectException: другой объект с тем же значением идентификатора уже был связан с сеансом

Например:

A table
|   ID  |   B_ID    |   C_ID    |
|    1  |      1    |   null    |    // this works
|    2  |   null    |      1    |    // this works
|    3  |      1    |      x    |    // this throws the exception
|    4  |      x    |      1    |    // this throws the exception

x=any value of existent B/C_ID 

B_ID и C_ID не являются уникальными в моей модели, и (B_ID + C_ID) не является уникальным ограничением !!

Что я могу сделать?

Спасибо заранее.

1 Ответ

16 голосов
/ 23 августа 2010

Hibernate не жалуется на уникальность базы данных, он жалуется, что текущий Session уже содержит объект с тем же идентификатором, что и новый объект, который вы пытаетесь сохранить.Это не допустит - Hibernate имеет строгое требование, чтобы данный идентификатор не мог быть представлен двумя разными объектами в рамках одного сеанса.

В какой-то момент ваше приложение сохранило или загрузило объект с тем же идентификатором, и этот объект уже "зарегистрирован" в сеансе.В данном конкретном случае сложно сказать, на какой идентификатор он жалуется, поскольку текст исключения неясен.Попробуйте временно удалить каскадные директивы и посмотреть, если это все еще происходит, попробуйте сузить.

При необходимости вы можете заставить сеанс «забыть» о любых существующих объектах для данного идентификатора (используя Session.evict() в API Hibernate или EntityManager.detach() в API JPA 2.0), но это не такочень элегантное решение.

Повторюсь - это исключение не имеет ничего общего с ограничениями базы данных, оно касается защиты Hibernate от согласованности состояния внутренней памяти.

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