Ошибка гибернации: орг.зимовать.NonUniqueObjectException: другой объект с тем же значением идентификатора уже был связан с сеансом
у меня есть два объекта пользователя и пока я пытаюсь сохранить объект с помощью
session.save(userObj);
Я получаю следующую ошибку:
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
[com.pojo.rtrequests.User#com.pojo.rtrequests.User@d079b40b]
Я создаю сеанс с помощью
BaseHibernateDAO dao = new BaseHibernateDAO();
rtsession = dao.getSession(userData.getRegion(),
BaseHibernateDAO.RTREQUESTS_DATABASE_NAME);
rttrans = rtsession.beginTransaction();
rttrans.begin();
rtsession.save(userObj1);
rtsession.save(userObj2);
rtsession.flush();
rttrans.commit();
rtsession.close(); // in finally block
Я тоже пробовал делать session.clear() перед сохранением, все-таки не повезло.
это для первого я получаю объект сеанса, когда приходит запрос пользователя, поэтому я получаю, почему говорит, что объект присутствует в сеансе.
какие предложения?
30 ответов:
У меня была эта ошибка много раз, и это может быть довольно трудно отследить...
в принципе, hibernate говорит, что у вас есть два объекта, которые имеют один и тот же идентификатор (один и тот же первичный ключ), но они не являются одним и тем же объектом.
Я бы предложил вам разбить свой код, т. е. закомментировать биты, пока ошибка не исчезнет, а затем вернуть код, пока он не вернется, и вы должны найти ошибку.
Это чаще всего происходит через каскадные спасает где есть каскадное сохранение между объектом A и B, но объект B уже был связан с сеансом, но не на том же экземпляре B.
какой генератор первичных ключей вы используете?
причина, по которой я спрашиваю, эта ошибка связана с тем, как вы говорите hibernate, чтобы установить постоянное состояние объекта (т. е. является ли объект постоянным или нет). Ошибка может произойти, потому что hibernate пытается сохраниться и объект, который уже является постоянным. На самом деле, если вы используете save hibernate попытается сохранить этот объект, и, возможно, уже есть объект с тем же первичным ключом, связанным с сеансом.
пример
предполагая, что у вас есть объект класса hibernate для таблицы с 10 строками на основе комбинации первичных ключей (столбец 1 и столбец 2). Теперь, вы сняли 5 строк из таблицы в какой-то момент времени. Теперь, если вы попытаетесь добавить те же 10 строк снова, в то время как hibernate пытается сохраниться объекты в базе данных, 5 строк, которые уже были удалены, будут добавлены без ошибок. Теперь оставшиеся 5 строк, которые уже существуют, будут выбрасывать это исключение.
таким образом, простой подход будет проверять, если вы обновили / удалили любое значение в таблице, которая является частью чего-то, а затем вы пытаетесь вставить те же объекты снова
Это только одна точка, где hibernate создает больше проблем, чем решает. В моем случае есть много объектов с одинаковым идентификатором 0, потому что они новые и не один. БД генерирует их. Где-то я читал, что 0 сигналов Id не установлен. Интуитивный способ сохранить их-это перебирать их и говорить hibernate, чтобы сохранить объекты. Но вы не можете этого сделать - "конечно, вы должны знать, что hibernate работает так и так, поэтому вы должны.." Так что теперь я могу попробовать измените идентификаторы на Long вместо long и посмотрите, работает ли он. В конце концов, это проще сделать с помощью простого картографа самостоятельно, потому что hibernate-это просто дополнительная непрозрачная нагрузка. Другой пример: попытка прочитать параметры из одной базы данных и сохранить их в другой заставляет вас выполнять почти всю работу вручную. Но если вам все равно нужно это сделать, использование hibernate-это просто дополнительная работа.
использовать
session.evict(object);функцииevict()метод используется для удаления экземпляра из кэша сеанса. Поэтому для первого сохранения объекта сохраните объект, вызвавsession.save(object)метод перед удалением объекта из кэша. Таким же образом обновите объект, вызвавsession.saveOrUpdate(object)илиsession.update(object)перед вызовом выселить().
Это может произойти, когда вы использовали тот же объект сеанса для чтения и записи. Как? Допустим, вы создали один сеанс. Вы читаете запись из таблицы employee с первичным ключом Emp_id=101 Теперь вы изменили запись в Java. И вы собираетесь сохранить запись сотрудника в базе данных. у нас есть не закрытые сессии где-то здесь. Поскольку объект, который был прочитан, также сохраняется в сеансе. Он конфликтует с объектом, который мы хотим записать. Отсюда и возникает эта ошибка.
Как кто-то уже указал выше, я столкнулся с этой проблемой когда у меня было
cascade=allна обоих концахone-to-manyотношения, поэтому давайте предположим, что A --> B (один ко многим из A и многие к одному из B) и обновлял экземпляр B В A, а затем вызывал saveOrUpdate ( A), это приводило к циклическому запросу сохранения, т. е. сохранению триггеров сохранения B, которые запускают сохранение A... и в третьем случае в качестве сущности (из A) была предпринята попытка добавить в sessionPersistenceContext duplicateObject исключение было брошено.
я мог бы решить эту проблему, удалив каскад с одного конца.
получить объект внутри сеанса, вот пример:
MyObject ob = null; ob = (MyObject) session.get(MyObject.class, id);
я столкнулся с этой проблемой:
- удаление объекта (с помощью HQL)
- немедленно сохранение нового объекта с тем же идентификатором
Я решил это путем промывки результаты после удаления и очистки кэша перед сохранением нового объекта
String delQuery = "DELETE FROM OasisNode"; session.createQuery( delQuery ).executeUpdate(); session.flush(); session.clear();
Я также столкнулся с этой проблемой и было трудно найти ошибку.
проблема у меня была следующая:
объект был прочитан Dao с другим сеансом гибернации.
чтобы избежать этого исключения, просто перечитайте объект с dao, который собирается сохранить / обновить этот объект позже.
так:
class A{ readFoo(){ someDaoA.read(myBadAssObject); //Different Session than in class B } } class B{ saveFoo(){ someDaoB.read(myBadAssObjectAgain); //Different Session than in class A [...] myBadAssObjectAgain.fooValue = 'bar'; persist(); } }надеюсь, что сэкономить некоторым людям много времени!
я столкнулся с этой проблемой при удалении объекта, ни выселить, ни помог.
/** * Deletes the given entity, even if hibernate has an old reference to it. * If the entity has already disappeared due to a db cascade then noop. */ public void delete(final Object entity) { Object merged = null; try { merged = getSession().merge(entity); } catch (ObjectNotFoundException e) { // disappeared already due to cascade return; } getSession().delete(merged); }
ваши Id сопоставления правильно? Если база данных отвечает за создание идентификатора через идентификатор, вам нужно сопоставить ваш userobject с этим ..
проверьте, если вы забыли поставить @GenerateValue для столбца @Id. У меня была такая же проблема со многими отношениями между фильмом и жанром. Программу забросил Ошибка гибернации: орг.зимовать.NonUniqueObjectException: другой объект с тем же значением идентификатора уже был связан с сеансом ошибка. Позже я узнал, что мне просто нужно убедиться, что у вас есть @GenerateValue для метода GenreId get.
просто проверьте идентификатор, принимает ли он значение null или 0, как
if(offersubformtwo.getId()!=null && offersubformtwo.getId()!=0)в add или update, где содержимое устанавливается из формы в Pojo
у меня была похожая проблема. В моем случае я забыл установить
increment_byзначение в базе данных должно быть таким же, как тот, который используетсяcache_sizeиallocationSize. (Стрелки указывают на указанные атрибуты)SQL:
CREATED 26.07.16 LAST_DDL_TIME 26.07.16 SEQUENCE_OWNER MY SEQUENCE_NAME MY_ID_SEQ MIN_VALUE 1 MAX_VALUE 9999999999999999999999999999 INCREMENT_BY 20 <- CYCLE_FLAG N ORDER_FLAG N CACHE_SIZE 20 <- LAST_NUMBER 180Java:
@SequenceGenerator(name = "mySG", schema = "my", sequenceName = "my_id_seq", allocationSize = 20 <-)
иное, чем то, что wbdarby сказал, это даже может произойти, когда объект извлекается, давая идентификатор объекта в HQL. В случае попытки изменить поля объекта и сохранить его обратно в БД (модификация может быть insert, delete или update)за тот же сеанс эта ошибка появится. Попробуйте очистить сеанс гибернации перед сохранением измененного объекта или создать новый сеанс.
Надеюсь, я помог ; -)
у меня та же ошибка, я заменял свой набор на новый, полученный от Джексона.
чтобы решить эту проблему, я сохраняю существующий набор, я удаляю из старого набора элемент unknown в новый список с
retainAll. Затем я добавляю новые сaddAll.this.oldSet.retainAll(newSet); this.oldSet.addAll(newSet);нет необходимости иметь сеанс и манипулировать им.
попробуйте это. Ниже работал для меня!
на
hbm.xmlfile
нам нужно установить
dynamic-updateатрибут класса tag totrue:<class dynamic-update="true">установите атрибут class тега генератора под уникальным столбцом в
identity:<generator class="identity">Примечание: установите уникальный столбец в
identity, а неassigned.
еще одна вещь, которая работала для меня, состояла в том, чтобы сделать переменную экземпляра Long вместо long
у меня была переменная первичного ключа long id; изменение его на Long id; работалвсего наилучшего
вы всегда можете сделать сеанс заподлицо. Flush синхронизирует состояние всех ваших объектов в сеансе (пожалуйста, кто-то поправит меня, если я ошибаюсь), и, возможно, это решит вашу проблему в некоторых случаях.
реализация собственных равных и хэш-код может помочь вам тоже.
вы можете проверить настройки каскада. Каскадные настройки на ваших моделях могут быть причиной этого. Я удалил настройки каскада (по существу, не разрешая каскадные вставки / обновления), и это решило мою проблему
Я тоже нашел эту ошибку. То, что сработало для меня,-это убедиться, что первичный ключ (который автоматически генерируется) не является PDT (т. е. long, int, ect.), но объект (т. е. длинный, целочисленный и т. д.)
при создании объекта для его сохранения убедитесь, что вы передаете null, а не 0.
Я новичок в NHibernate, и моя проблема заключалась в том, что я использовал другой сеанс для запроса моего объекта, чем для его сохранения. Таким образом, сеанс сохранения не знал об объекте.
Это кажется очевидным, но из чтения предыдущих ответов я искал везде 2 объекта, а не 2 сеанса.
это поможет?
User userObj1 = new User(); User userObj2 = userObj1; . . . rtsession.save(userObj1); rtsession.save(userObj2);
@GeneratedValue (strategy=GenerationType.IDENTITY), добавление этой аннотации к свойству первичного ключа в вашем компоненте Сущности должно решить эту проблему.
Я решил эту проблему .
На самом деле это происходит потому, что мы забыли реализацию типа генератора свойства PK в классе bean. Так что сделайте это любой тип, как@Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id;когда мы сохраняем объекты bean, каждый объект получает тот же идентификатор ,поэтому первый объект сохраняется ,когда другой объект будет сохраняться, а затем HIB FW через этот тип
Exception: org.hibernate.NonUniqueObjectException:другой объект с тем же значение идентификатора уже был связан с сессии.
Я решил подобную проблему так:
plan = (FcsRequestPlan) session.load(plan.getClass(), plan.getUUID()); while (plan instanceof HibernateProxy) plan = (FcsRequestPlan) ((HibernateProxy) plan).getHibernateLazyInitializer().getImplementation();
перед позицией, где начинаются повторяющиеся объекты, вы должны закрыть сеанс и тогда вы должны начать новую сессию
session.close(); session = HibernateUtil.getSessionFactory().openSession();таким образом, в одном сеансе существует не более одной сущности, имеющей один и тот же идентификатор.
проблема возникает из-за того, что в одном сеансе гибернации вы пытаетесь сохранить два объекта с одинаковым идентификатором.Есть два решения:-
это происходит потому, что вы не настроили отображение.xml-файл правильно для полей id, как показано ниже: -
<id name="id"> <column name="id" sql-type="bigint" not-null="true"/> <generator class="hibernateGeneratorClass"</generator> </id>перегрузите метод getsession, чтобы принять такой параметр, как isSessionClear, и очистите сеанс перед возвратом текущего сеанса, например ниже
public static Session getSession(boolean isSessionClear) { if (session.isOpen() && isSessionClear) { session.clear(); return session; } else if (session.isOpen()) { return session; } else { return sessionFactory.openSession(); } }это приведет к очистке существующих объектов сеанса, и даже если hibernate не генерирует уникальный идентификатор ,предполагая,что вы правильно настроили свою базу данных для первичного ключа, используя что-то вроде Auto_Increment, он должен работать для вас.
один обходной путь для решения этой проблемы-попытаться прочитать объект обратно из hibernate cache / db, прежде чем делать какие-либо обновления, а затем сохраниться.
пример:
OrderHeader oh = orderHeaderDAO.get(orderHeaderId); oh.setShipFrom(facilityForOrder); orderHeaderDAO.persist(oh);Примечание: имейте в виду, что это не устраняет основную причину, но решает проблему.
поздно на вечеринку, но может помочь для будущих пользователей -
Я получил эту проблему, когда я выберите записи с помощью
getsession()и снова обновление еще одна запись с тем же идентификатор используя сессии вызывает проблемы. Добавлен код ниже.Customer existingCustomer=getSession().get(Customer.class,1); Customer customerFromUi;// This customer details comiong from UI with identifer 1 getSession().update(customerFromUi);// Here the issue comesэто не должно быть сделано . Решение-либо удалить сеанс перед обновлением, либо изменить бизнес-логику.
можно использовать
session.merge(obj), Если вы выполняете сохранение с разными сеансами с одним и тем же идентификатором persistent object.
Это сработало, у меня была такая же проблема раньше.
Comments