Ошибка удаления гибернации: пакетное обновление возвращено Неожиданное количество строк
Я написал этот метод ниже, который должен удалить запись элемента из базы данных. Но когда я использую его в своем сервлете, он возвращает ошибку.
Класс MemberDao
public static void deleteMember(Member member) {
Session hibernateSession = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = hibernateSession.beginTransaction();
hibernateSession.delete(member);
tx.commit();
}
Контрольная часть
if(delete != null) {
HttpSession httpSession = request.getSession();
Member member = (Member) httpSession.getAttribute("member");
MemberDao.deleteMember(member);
nextPage = "ledenlijst.jsp";
}
Состояние HTTP 500
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
Иногда это даже вызывает эту ошибку, когда я пытаюсь выполнить страницу несколько раз.
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
Кто-нибудь знает, что именно вызывает эти ошибки?
Ответы
Ответ 1
Ошибка может быть вызвана несколькими вещами. Я не беру на себя ответственность за это, нашел здесь.
- Промывка данных перед фиксацией объекта может привести к очистке всех объект, ожидающий сохранения.
- Если объект имеет первичный ключ, который автоматически генерируется, и вы принудительно назначенный ключ
- если вы очищаете объект перед тем, как передать объект базы данных.
- Нулевой или неправильный идентификатор: если вы установили идентификатор в ноль или что-то еще, Hibernate будет пытаться обновить вместо вставки.
- Объект Stale: Hibernate кэширует объекты из сеанса. Если объект был изменен, и Hibernate не знает об этом, он будет бросить это исключение - обратите внимание на StaleStateException
Также посмотрите этот ответ beny23, в котором содержится несколько дополнительных советов, чтобы найти проблему.
- В вашей конфигурации спящего режима установите для hibernate.show_sql значение true. Это должно показать вам SQL, который выполняется и вызывает проблему.
- Задайте уровни журналов для Spring и Hibernate для DEBUG, это даст вам более полное представление о том, какая строка вызывает проблему.
- Создайте unit test, который реплицирует проблему без настройки диспетчера транзакций в Spring. Это должно дать вам лучшее представление о нарушении кода.
Ответ 2
Исключение
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
использовать, чтобы быть брошенным, когда Hibernate заметил, что объект, который он хочет сбросить в базу данных, не совсем так, как это было в начале транзакции.
Я подробно описал два разных варианта использования, которые происходят со мной здесь.
Ответ 3
В моем случае это исключение было вызвано неправильным сопоставлением объектов. Касади для отношения не было, и связанный дочерний объект не был сохранен, прежде чем пытаться ссылаться на него от родителя. Изменение его на
@OneToMany(cascade = CascadeType.ALL)
исправлена проблема.
Разумеется, лучший способ найти причину этого исключения - установить show_sql и уровень DEBUG для журналов - он остановится только на sql, который вызвал проблему.
Ответ 4
Я столкнулся с такой же проблемой.
Код работал в тестовой среде. Но он не работал в промежуточной среде.
org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 3; expected: 1
Проблема заключалась в том, что в таблице была одна запись для каждого первичного ключа при тестировании таблицы БД. Но в промежуточной БД было несколько записей для того же первичного ключа. (Проблема заключается в промежуточном БД, в таблице не было ограничений первичного ключа, также было несколько записей.)
Поэтому каждый раз при обновлении он получает сбой. Он пытается обновить одну запись и ожидать, что количество обновлений будет равным 1. Но поскольку в таблице для одного и того же первичного ключа было 3 записи, число результатов обновления результата 3. Поскольку ожидаемое количество обновлений и фактический результат обновления не совпадают, Он выдает исключение и откатывается.
После того, как я удалил все записи, которые имеют дублирующий первичный ключ и добавили ограничения первичного ключа. Он работает нормально.
Ответ 5
это решение для моего дела, возможно, это поможет вам!
На самом деле это была проблема преобразования между типом поля базы данных (timestamp on postgreSQL) и его эквивалентным типом свойств (Calendar) в файле hibernate xml.
Когда Hibernate выполнил этот запрос на обновление, он не извлекал строку, потому что запрос запрашивал с плохим преобразованием значения календаря.
Поэтому я просто заменил тип свойства "Календарь" в "Дата" в файле Hibernate xml и проблема была исправлена.
Ответ 6
Я недавно испытал это, и произошло то, что я использовал метод обновления, и он выбрасывал исключение, потому что не было существующей записи. Я изменил метод saveOrUpdate. Это сработало.
Ответ 7
У меня возникла такая же проблема с hibernate/JPA 2.1 при использовании memcached в качестве вторичного кеша. Вы получите исключение выше, а также исключение StaleStateException. Резолюция была иной, чем было отмечено ранее.
Я заметил, что если у вас есть операция, которая чередует удаленные и выбирает (находит) из одной и той же таблицы и транзакции, спящий режим может стать перегруженным и сообщить об этом исключении статического состояния. Это произойдет только для нас во время производства, поскольку в одной таблице будут происходить несколько идентичных операций с разными объектами. Вы увидите системный тайм-аут и забрасываете исключения.
Решение состоит в том, чтобы просто быть более эффективным. Вместо того, чтобы чередовать в цикле, попытайтесь решить, какие элементы нужно читать и делать это, желательно в одну операцию. Затем выполните удаление в отдельной операции. Опять же, все в одной и той же транзакции, но не перебирайте спящий режим с помощью операций чтения/удаления/чтения/удаления.
Это намного быстрее и значительно снижает нагрузку на обслуживание на Спящем. Проблема исчезла. Это происходит, если вы используете дополнительный кеш и иначе не будет возникать иначе, поскольку загрузка будет находиться в базе данных для разрешения без дополнительного кеша. Это еще одна проблема.
Ответ 8
У меня была эта проблема,
Я проверил свой код, проблем не было, но когда я проверил свои данные, я обнаружил, что у меня было два объекта с одним и тем же идентификатором!
Итак, flush()
не может работать, потому что он работает один за другим для пакетных обновлений и обнаружил 2 строки. Поэтому он не обновлял и не вводил исключение, но это была моя проблема. Я не знаю, хорошо ли это для вас или нет!