Ошибка гибернации: орг.зимовать.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() перед сохранением, все-таки не повезло.



это для первого я получаю объект сеанса, когда приходит запрос пользователя, поэтому я получаю, почему говорит, что объект присутствует в сеансе.



какие предложения?

721   30  

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);

я столкнулся с этой проблемой:

  1. удаление объекта (с помощью HQL)
  2. немедленно сохранение нового объекта с тем же идентификатором

Я решил это путем промывки результаты после удаления и очистки кэша перед сохранением нового объекта

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     180

Java:

@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.xml file

  1. нам нужно установить dynamic-update атрибут класса tag to true:

    <class dynamic-update="true">
    
  2. установите атрибут 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();

таким образом, в одном сеансе существует не более одной сущности, имеющей один и тот же идентификатор.

проблема возникает из-за того, что в одном сеансе гибернации вы пытаетесь сохранить два объекта с одинаковым идентификатором.Есть два решения:-

  1. это происходит потому, что вы не настроили отображение.xml-файл правильно для полей id, как показано ниже: -

    <id name="id">
      <column name="id" sql-type="bigint" not-null="true"/>
      <generator class="hibernateGeneratorClass"</generator>
    </id>
    
  2. перегрузите метод 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

    Ничего не найдено.