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

98

У меня есть два пользовательских объекта, и пока я пытаюсь сохранить объект, используя

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#[email protected]]

Я создаю сессию, используя

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() до сохранения все равно не повезло.

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

Какие-либо предложения

Связанная ссылка Stackoverflow.com / а / 32270237/1793718 Lucky
Вот еще одна замечательная тема, которая помогла решить мою проблему Getj2ee.over-blog.com / ... Reddymails

Ваш Ответ

29   ответов
4

Удаление объекта (с использованием HQL) Немедленно хранит новый объект с тем же идентификатором

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

String delQuery = "DELETE FROM OasisNode";
session.createQuery( delQuery ).executeUpdate();
session.flush();
session.clear();
3

Получите объект внутри сеанса, вот пример:

MyObject ob = null;
ob = (MyObject) session.get(MyObject.class, id);
Хорошая попытка, но объект "ob" возвращается без обновленных данных (учитывая, что он обновлялся через приложение во время выполнения, между объектами, извлекаемыми из базы данных и их сохранением). Alex
164

и отследить ее может быть довольно сложно ...

В основном hibernate говорит о том, что у вас есть два объекта, которые имеют один и тот же идентификатор (один и тот же первичный ключ), но это не один и тот же объект.

Я бы посоветовал вам разбить ваш код, то есть закомментировать биты, пока ошибка не исчезнет, а затем вернуть код обратно, пока он не вернется, и вы должны найти ошибку.

Чаще всего это происходит посредством каскадного сохранения, когда между объектом A и B происходит каскадное сохранение, но объект B уже связан с сеансом, но не в том же экземпляре B.

Какой генератор первичного ключа вы используете?

Причина, по которой я спрашиваю, заключается в том, что эта ошибка связана с тем, как вы сообщаете в спящий режим, чтобы определить постоянное состояние объекта (т. Е. Является ли объект постоянным или нет). Ошибка может произойти, потому что hibernate пытается сохранить и объект, который уже является постоянным. Фактически, если вы используете save hibernate, он попытается сохранить этот объект, и, возможно, уже существует объект с тем же первичным ключом, связанным с сеансом.

Приме

Предполагая, что у вас есть объект класса hibernate для таблицы с 10 строками на основе комбинации первичных ключей (столбец 1 и столбец 2). Теперь вы удалили 5 строк из таблицы в определенный момент времени. Теперь, если вы попытаетесь снова добавить те же 10 строк, а hibernate попытается сохранить объекты в базе данных, 5 уже удаленных строк будут добавлены без ошибок. Теперь оставшиеся 5 строк, которые уже существуют, выдают это исключение.

Так что простой подход - это проверить, обновили ли вы / удалили ли какое-либо значение в таблице, которая является частью чего-то, а позже вы пытаетесь вставить те же самые объекты снова

Отличный ответ². Первичным ключом была моя проблема, решаемая с помощью GeneratedValue, устанавливающей последовательность для postgresql. Rodrigo Ferrari
У меня была такая же проблема. В моем случае у меня был поиск объекта в коде, и я пытался создать новый объект с тем же идентификатором в другом фрагменте кода, пока первый объект еще находился в сеансе hibernate. dellasavia
18

когда гибернация создает больше проблем, чем решает. В моем случае есть много объектов с одинаковым идентификатором 0, потому что они новые и не имеют таковых. БД генерирует их. Где-то я читал, что 0 сигналов не установлены. Интуитивно понятный способ их сохранения состоит в том, чтобы перебирать их и произносить hibernate для сохранения объектов. Но Вы не можете этого сделать - «Конечно, Вы должны знать, что hibernate работает так и так, поэтому Вы должны…». Теперь я могу попытаться изменить Ids на Long вместо long и посмотреть, будет ли это работать. В конце концов, проще сделать это с помощью простого средства отображения, потому что спящий режим - это просто дополнительное непрозрачное бремя. Другой пример. Попытка чтения параметров из одной базы данных и сохранения их в другой вынуждает выполнять почти всю работу вручную. Но если вам все равно придется это делать, использование hibernate - это просто дополнительная работа.

Я тоже ненавижу hibernate ... и базы данных ... После всех проблем, которые они мне вызвали, я думаю, проще использовать текстовый файл (я шучу, но все же ...). Igor Popov
В моем случае есть много объектов с одинаковым идентификатором 0, потому что они новые и не имеют таковых. БД генерирует их. Где-то я читал, что 0 сигналов не установлены. Интуитивно понятный способ их сохранения - это итерация по ним и переход в режим гибернации для сохранения объекто. Мне нужно сделать именно это. Не могли бы вы сказать мне, каков «спящий» способ сделать это? Ramses
В моем случае мне пришлось использовать session.merge (myobject), так как у меня было два экземпляра этого объекта. Обычно это происходит, когда сущность сохраняется и отсоединяется от сеанса. Другой экземпляр этого объекта запрашивается в спящем режиме. Этот второй экземпляр оставался прикрепленным к сеансу. Первый экземпляр изменен. Больше на Getj2ee.over-blog.com / ... Reddymails
проблема не в спячке, а в непонимании того, как это работает ACV
13

session.evict(object); Функцияevict()етод @ используется для удаления экземпляра из кэша сеанса. Так что для первого сохранения объекта сохраните объект, вызвавsession.save(object) метод перед удалением объекта из кэша. Таким же образом обновите объект, вызвавsession.saveOrUpdate(object) илиsession.update(object) перед вызовом evict ().

8

если вы использовали один и тот же объект сеанса для чтения и записи. Как? Скажем, вы создали одну сессию. Вы читаете запись из таблицы сотрудников с первичным ключом Emp_id = 101. Теперь вы изменили запись в Java. И вы собираетесь сохранить запись сотрудника в базе данных. мы нигде здесь не закрыли сессию. Поскольку объект, который был прочитан, также сохраняется в сеансе. Это конфликтует с объектом, который мы хотим написать. Отсюда и эта ошибка.

7

я столкнулся с этой проблемой, когда у меня былcascade=all на обоих концахone-to-many отношение, так что давайте предположим, что A -> B (один-ко-многим из A и многие-к-одному из B) и обновляли экземпляр B в A, а затем вызывали saveOrUpdate (A), что приводило к циклическому запрос на сохранение, т. е. сохранение A вызывает сохранение B, которое вызывает сохранение A ... и в третьем случае, когда объект (из A) пытался добавить в sessionPersistenceContext, было выдано исключение duplicateObject.
Я могу решить эту проблему, сняв каскад с одного конца.

Решил мою проблему вместе с / Stackoverflow.com вопросы / 4334970 / ... Magno C
4

У меня была следующая проблема:

Объект был прочитан Дао с другим сеансом гибернации.

Чтобы избежать этого исключения, просто перечитайте объект с помощью дао, который позже сохранит / обновит этот объект.

так

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

}

Надеюсь, это сэкономит людям много времени!

2

ни удаление, ни очистка не помогли.

/**
 * 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);
}
1

ификатора с помощью идентификатора, вам необходимо сопоставить свой пользовательский объект с этим ..

да, мое отображение идентификатора правильное и уникальный идентификатор передан harshit
1

если вы забыли поставить @GenerateValue для столбца @Id. У меня была та же проблема со многими отношениями между фильмом и жанром. Программа вызвала ошибку Hibernate: org.hibernate.NonUniqueObjectException: другой объект с таким же значением идентификатора уже был связан с ошибкой сеанса. Позже я узнал, что мне просто нужно убедиться, что у вас есть @GenerateValue для метода get GenreId.

1

принимает ли он ноль или 0, как

if(offersubformtwo.getId()!=null && offersubformtwo.getId()!=0)

в добавлении или обновлении, где содержание устанавливается из формы в Pojo

1

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

Это кажется очевидным, но, прочитав предыдущие ответы, я искал везде 2 объекта, а не 2 сессии.

1

@ GeneratedValue (стратегии = GenerationType. добавление этой аннотации к свойству первичного ключа в вашем компоненте должно решить эту проблему.

1

где начинаются повторяющиеся объекты, вы должны закрыть сеанс, а затем начать новый сеанс

session.close();      
session = HibernateUtil.getSessionFactory().openSession();

Таким образом, в одном сеансе не более одного объекта с одинаковым идентификатором.

1

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

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

<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, он должен работать для вас.

1

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

Джава

@SequenceGenerator(name = "mySG", schema = "my", 
sequenceName = "my_id_seq", allocationSize = 20 <-)
1

Wbdarby сказал, что это даже может произойти, когда объект выбирается путем предоставления идентификатора объекта HQL. В случае попытки изменить поля объекта и сохранить его обратно в БД (изменение может быть вставка, удаление или обновление) за ту же сессию, эта ошибка появится. Попробуйте очистить сеанс гибернации перед сохранением измененного объекта или создайте новый сеанс.

Надеюсь, я помог; -)

1

что я заменял свой Сет новым, полученным от Джексона.

Чтобы решить эту проблему, я сохраняю существующий набор, я удаляю из старого набора элемент, неизвестный в новый список, с помощьюretainAll. Затем я добавляю новые сaddAll.

    this.oldSet.retainAll(newSet);
    this.oldSet.addAll(newSet);

Нет необходимости иметь сессию и манипулировать ею.

1

session.merge(obj), если вы делаете сохранение с разными сеансами с одинаковым идентификатором персистентного объекта.
Это сработало, раньше у меня была такая же проблема.

0

которая работала для меня, состояла в том, чтобы сделать переменную экземпляра Long вместо long


У меня была переменная первичного ключа long id; изменив его на длинный идентификатор; работа

Всего наилучшег

0

сех ваших объектов в сеансе (пожалуйста, кто-нибудь исправит меня, если я ошибаюсь), и, возможно, в некоторых случаях это решит вашу проблему.

Внедрение собственных равных и хэш-кода также может вам помочь.

0

моделях могут быть причиной этого. Я удалил Cascade Settings (по сути, не позволяющий Cascade Inserts / Updates), и это решило мою проблем

0

чтобы убедиться, что первичный ключ (который генерируется автоматически) - это не PDT (то есть long, int, ect.), А объект (то есть Long, Integer и т. Д.)

Когда вы создаете объект, чтобы сохранить его, убедитесь, что вы передаете ноль, а не 0.

0

Это помогает?

User userObj1 = new User();
User userObj2 = userObj1;
.
.
.
rtsession.save(userObj1);
rtsession.save(userObj2); 
0

Я решил эту проблему.
На самом деле это происходит потому, что мы забыли реализацию свойства PK типа генератора в классе компонента. Так что сделайте это любым типом как

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

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

0

plan = (FcsRequestPlan) session.load(plan.getClass(), plan.getUUID());
while (plan instanceof HibernateProxy)
    plan = (FcsRequestPlan) ((HibernateProxy) plan).getHibernateLazyInitializer().getImplementation();
0

братно из hibernate cache / db, прежде чем делать какие-либо обновления, а затем сохранять его.

Пример

            OrderHeader oh = orderHeaderDAO.get(orderHeaderId);
            oh.setShipFrom(facilityForOrder);
            orderHeaderDAO.persist(oh);

Примечание: имейте в виду, что это не устраняет основную причину, но решает проблему.

0

Я получил эту проблему, когда яВыбрат запись с использованием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

Этого никогда не должно быть. Решение - либо исключить сессию перед обновлением, либо изменить бизнес-логику.

Похожие вопросы