NonUniqueObjectException Hibernate [дубликат]

Новое в 2014 году:

Особенно, если вы также заинтересованы в манипулировании данными в целом (включая сортировку, фильтрацию, подмножество, подведение итогов и т. д.), вам обязательно нужно взглянуть на dplyr, который поставляется с множеством функций, которые предназначены для облегчения вашей работы с кадрами данных и некоторыми другими типами баз данных. Он даже предлагает довольно сложный SQL-интерфейс и даже функцию для преобразования (большинства) SQL-кода непосредственно в R.

. Четыре функции, связанные с соединением в пакете dplyr, (цитата):

  • inner_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x, где в y есть соответствующие значения, а все столбцы из x и y
  • left_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x и все столбцы от x и y
  • semi_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x, где в y есть соответствующие значения, сохраняя только столбцы из x.
  • anti_join(x, y, by = NULL, copy = FALSE, ...): вернуть все строки из x, где в y нет совпадающих значений, сохраняя только столбцы из x

Здесь все здесь

Выбор столбцов может выполняться с помощью select(df,"column"). Если для вас недостаточно SQL-ish, то есть функция sql(), в которую вы можете ввести код SQL как есть, и он будет выполнять указанную вами операцию так же, как вы писали в R все время (для получения дополнительной информации , обратитесь к dplyr / database vignette ). Например, если применить правильно, sql("SELECT * FROM hflights") выберет все столбцы из таблицы dplyr «hflights» («tbl»).

42
задан Mat 8 May 2014 в 08:07
поделиться

7 ответов

Вы полностью правы во всех своих оценках. Вы получите это.

Для вашего первого вопроса, если я правильно назову, save специально вставляет. Поэтому вызов save снова приведет к другой строке в db.

Для вашего второго вопроса update обновляет объект в сеансе. Поэтому, если объект находится в сеансе, он будет обновляться. Если объект не находится в сеансе, вы должны вызвать слияние. Я считаю, что вызов update для отдельного экземпляра приведет к исключению.

9
ответ дан hvgotcodes 21 August 2018 в 22:25
поделиться
  • 1
    Спасибо hvgotcodes. Если вы можете дать краткий ответ о серой / цитируемой части, это будет очень полезно. – M Sach 19 September 2011 в 19:21
  • 2
    Привет hvgotcodes, я не думаю, что fisrt и второе объяснение верны. Поскольку проверка сохранения должна проверять значение идентификатора для нуля, но для уже постоянного объекта это не равно нулю. Поэтому он не вставляет новую строку. Что касается второго ответа в соответствии с обновлением документации api, также для отдельного объекта. Не уверен, если мы обновим уже постоянный объект, какой метод мы должны назвать? – M Sach 19 September 2011 в 19:39
  • 3
    @mohit, вы на самом деле пытались это сделать? верните единичный тест и попробуйте его. – hvgotcodes 19 September 2011 в 20:26
  • 4
    Ваш первый ответ неправильный. При вызове save (object) более одного раза спящий режим не будет запускать больше одного запроса в базу данных, потому что hibernate будет использовать свой первый уровень кэширования (сеанс), а спящий режим работает с прокси-сервером. – subhashis 11 December 2013 в 10:55
  • 5
    Собственно, как первый, так и второй ответы неверны. Вызов сохранения дважды в сеансе вызывает только одну вставку, вызывать обновление на постоянном объекте не нужно, но не вызывать исключения, и вы можете, конечно, вызывать обновление для отдельного объекта. – pzeszko 10 September 2015 в 06:54

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

Обновление предназначено для вызова на отдельные объекты, то есть те, которые находятся за пределами сеанса, который они загружали in. @hvgotcodes кажется неправильным, потому что обновление следует вызывать, только если объект не в сеансе. обновление может завершиться неудачно, если экземпляр объекта уже находится в сеансе. В этом случае следует использовать слияние. Он объединяет изменения отдельного объекта с объектом в сеансе, если он существует. Если в сеансе нет объекта, он создаст новый.

. Часто вы можете вообще не вызывать обновление / слияние, но если вам в итоге нужно позвонить, слияние обрабатывает более широкий диапазон ситуации. Мое понимание - единственная причина использования обновления для лучшей производительности, если вы знаете, что это не будет ошибкой.

В этой теме есть довольно хорошее резюме некоторых других методов спящего режима,

Редактирование: я просто подумал, что должен сказать, что между слиянием и обновлением больше различий, чем я изначально сказал. Обновление изменяет данный объект на постоянный, тогда как merge возвращает новый постоянный объект. Для слияния вы должны выбросить старый объект. Другое отличие заключается в том, что слияние выполняет грязную проверку, выбирая из БД, прежде чем принимать решение о том, следует ли записывать свои данные, тогда как обновление всегда сохраняет свои данные в БД независимо от того, грязно это или нет.

Есть, вероятно, другие небольшие отличия. Всегда полезно проверять поведение Hibernate, регистрируя сгенерированный SQL, потому что поведение не всегда соответствует документам, по крайней мере, по моему опыту.

30
ответ дан Community 21 August 2018 в 22:25
поделиться

Вы должны применить разницу между методами save () и saveOrUpdate в своем коде, чтобы получить максимальную производительность:

Метод save () возвращает идентификатор, сгенерированный базой данных. С другой стороны, saveOrUpdate () может выполнять INSERT или UPDATE в зависимости от того, существует ли объект в базе данных или нет. И saveOrUpdate делает выбор сначала, чтобы определить, нужно ли ему вставлять или обновлять. Таким образом, вы должны использовать saveOrUpdate в случае запроса на обновление.

Еще одно ключевое различие между методом save () и saveOrUpdate () заключается в том, что метод save () используется, чтобы сделать переходный объект постоянным, но saveOurUpdate () может сделать переходный (новый объект) и отдельный (существующий объект) объект в постоянное состояние. Так что saveOrUpdate () часто используется для повторного присоединения отдельного объекта к сеансу.

Из сообщения Разница между save и saveOrUpdate в спящем режиме

0
ответ дан David Pham 21 August 2018 в 22:25
поделиться

session.update () - используется для сценария, когда вы загружаете объект Person1 из сеанса спящего режима. Теперь он используется в приложении - также может быть на стороне клиента, был обновлен. Мы хотим сохранить его снова. Мы знаем, что никаких изменений в объекте Person в базе данных не было. Поэтому мы можем просто использовать обновление.

session.merge () - В приведенном выше сценарии, если изменения были сделаны в личных данных перед сохранением измененного объекта Person1, тогда мы должны использовать слияние. Он объединит изменения.

session.save () - его можно использовать для сохранения нового объекта. Он возвращает сериализуемое удостоверение.

session.persist () - То же, что и save (), но является методом void и ничего не возвращает.

session.saveOrUpdate () - Этот метод будет работать как для новых, так и для старых объектов. Если объект новый, он будет работать как простое сохранение или если объект уже настойчив, он будет работать как обновление.

session.lock () - Используется только для блокировки объекта или вы можете сказать, чтобы проверить версию объекта. Он не предназначен для обновления объекта. Он должен использоваться для повторного подключения объекта, только если вы уверены, что состояние объекта в базе данных уже не изменено. В противном случае он может переопределить изменения. & Lt; Приглашение большего количества баллов.

4
ответ дан Maclane 21 August 2018 в 22:25
поделиться

@Naliba дал отличный ответ по методу Update ().

Жизненный цикл гибернации в следующем изображении помогает получить представление выше методов.

Пример: рассмотрим ситуацию merge() метода.

SessionFactory factory = cfg.buildSessionFactory();
Session session1 = factory.openSession();

Student student1 = null;
Object object1 = session1.get(Student.class, new Integer(101));
student1 = (Student)object1;
session1.close();

student1.setMarks(97);// -->object will be in some RAM location, not in the session1 cache

Session session2 = factory.openSession();
Student student2 = null;
Object object2 = session2.get(Student.class, new Integer(101));
student2 = (Student)object2;
Transaction tx=session2.beginTransaction();

session2.merge(student1);

Выше student1 находится в отключенном состоянии, модифицировало этот отсоединенный объект student1, теперь, если мы позвоним update(), тогда hibernate выдает ошибку.

В этом session2, мы вызвали session2.merge(s1); теперь в student2 объект student1 изменения будут объединены и сохранены в базе данных.

6
ответ дан Premraj 21 August 2018 в 22:25
поделиться

Слияние происходит после

Слияние имеет интеллект. Он имеет много предварительных проверок, прежде чем он начнет слияние (если требуется)

  1. , если объект временно, просто запускает запрос INSERT, делает объект постоянным (прикрепленным к сеансу)
  2. если объект отсоединен, срабатывает запрос выбора, чтобы проверить, были ли данные изменены или нет, если они модифицированы, запускает запрос UPDATE, иначе просто игнорирует задачу слияния.

где в качестве session.update

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

session.merge is дороже, чем обновление

2
ответ дан Santh 21 August 2018 в 22:25
поделиться

update() предназначен для отдельных объектов, а для переходных объектов. если вызывать на постоянных объектах, он будет вызывать NonUniqueObjectException, и это будет рассмотрено merge().

3
ответ дан Sebastian 21 August 2018 в 22:25
поделиться
  • 1
    Я не думаю, что update для переходного объекта. StaleStateException будет выведено, если вы вызовете обновление в переходном объекте. – Ken Block 16 January 2015 в 04:19
Другие вопросы по тегам:

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