Hibernate - Пакетное обновление вернуло неожиданное количество строк из обновления: 0 фактическое количество строк: 0 ожидается: 1 - PullRequest
119 голосов
/ 30 апреля 2010

Я получаю следующее сообщение об ошибке гибернации. Я могу определить функцию, которая вызывает проблему. К сожалению, в этой функции есть несколько вызовов БД. Я не могу найти строку, которая вызывает проблему, поскольку hibernate завершает сеанс в конце транзакции. Приведенная ниже ошибка гибернации выглядит как общая ошибка. Это даже не упомянуло, какой Бин вызывает проблему. Кто-нибудь знаком с этой ошибкой гибернации?

org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
        at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:93)
        at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:79)
        at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
        at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransacti
onManager.java:500)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManag
er.java:473)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(Transaction
AspectSupport.java:267)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)

Ответы [ 30 ]

58 голосов
/ 09 ноября 2012

Я получил то же исключение при удалении записи по Id, которая вообще не существует. Поэтому убедитесь, что запись, которую вы обновляете / удаляете, действительно существует в БД

51 голосов
/ 30 апреля 2010

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

Однако, чтобы лучше понять причину проблемы, попробуйте следующее:

  • В вашей конфигурации hibernate установите для hibernate.show_sql значение true. Это должно показать вам SQL, который выполняется и вызывает проблему.
  • Установите для уровней журналов для Spring и Hibernate значение DEBUG, и это снова даст вам лучшее представление о том, какая строка вызывает проблему.
  • Создайте модульный тест, который повторяет проблему без настройки диспетчера транзакций в Spring. Это должно дать вам лучшее представление о неправильной строке кода.

Надеюсь, это поможет.

46 голосов
/ 07 мая 2014

Решение: В файле отображения Hibernate для свойства id, если вы используете какой-либо класс генератора, для этого свойства не следует устанавливать значение явно с помощью метода setter.

Если вы установите значение свойства Id явно, это приведет к ошибке выше. Проверьте это, чтобы избежать этой ошибки. или же Это ошибка, когда вы указываете в файле сопоставления поле generator = "native" или "incremental", и в вашей DATABASE сопоставленная таблица не является auto_incremented Решение. Перейдите в свою БАЗУ ДАННЫХ и обновите таблицу, установив auto_increment

.
17 голосов
/ 18 апреля 2014

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

9 голосов
/ 11 февраля 2014

Это может произойти, когда триггер (-ы) выполняют дополнительные запросы DML (изменение данных), которые влияют на количество строк. Моим решением было добавить следующее в верхней части моего триггера:

SET NOCOUNT ON;
8 голосов
/ 28 октября 2017

В моем случае я пришел к этому исключению в двух похожих случаях:

  • В методе, помеченном @Transactional, у меня был вызов в другую службу (с большим временем ответа). Метод обновляет некоторые свойства объекта (после метода объект все еще существует в базе данных). Если пользователь дважды запрашивает метод (поскольку он считает, что он не работает в первый раз) при выходе из транзакционного метода во второй раз, Hibernate пытается обновить сущность, которая уже изменила свое состояние с начала транзакции. Когда Hibernate ищет сущность в состоянии и обнаруживает ту же сущность, но уже измененную первым запросом, он выдает исключение, поскольку не может обновить сущность. Это как конфликт в GIT.
  • У меня были автоматические запросы (для мониторинга платформы), которые обновляют сущность (и откат вручную через несколько секунд). Но эта платформа уже используется командой тестирования. Когда тестер выполняет тест в том же объекте, что и автоматические запросы (в пределах одной сотой миллисекунды), я получаю исключение. Как и в предыдущем случае, при выходе из второй транзакции ранее извлеченный объект уже изменился.

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

Решение: чтобы решить эту проблему, вам придется поиграть с Hibernate LockMode , чтобы найти тот, который лучше всего соответствует вашим требованиям.

7 голосов
/ 08 февраля 2013

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

6 голосов
/ 25 августа 2015

Я столкнулся с той же проблемой. Код работал в среде тестирования. Но он не работал в промежуточной среде.

org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 3; expected: 1

Проблема заключалась в том, что таблица имела одну запись для каждого первичного ключа в тестируемой таблице БД. Но в промежуточной БД было несколько записей для одного и того же первичного ключа. (Проблема в том, что в промежуточной БД для таблицы не было ограничений первичного ключа, также было несколько записей.)

Таким образом, каждый раз при обновлении происходит сбой. Он пытается обновить одну запись и рассчитывает получить количество обновлений равным 1. Но поскольку в таблице было 3 записи для одного и того же первичного ключа, число обновлений результата находит 3. Поскольку ожидаемое количество обновлений и фактическое число обновлений результатов не совпадают , Выдает исключение и откатывается.

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

Hibernate - Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1

фактическое количество строк: 0 // означает, что запись не найдена для обновления
update: 0 // означает, что запись не найдена, поэтому ничего не обновляется
Ожидаемый: 1 // означает ожидаемую по крайней мере 1 запись с ключом в таблице базы данных.

Здесь проблема в том, что запрос пытается обновить запись для некоторого ключа, но hibernate не нашел ни одной записи с ключом.

5 голосов
/ 01 мая 2014

Я столкнулся с этой проблемой, когда у нас были отношения один-много.

В файле отображения hibernate hbm для мастера, для объекта с установленным расположением типов, добавлено cascade="save-update", и оно работало нормально.

Без этого hibernate по умолчанию пытается обновить несуществующую запись и вместо этого вставляет.

4 голосов
/ 29 августа 2013

Как Джулиус говорит, что это происходит, когда обновление происходит на объекте, дочерние элементы которого удаляются. (Вероятно, потому, что было необходимо обновление для всего Объекта Отца, и иногда мы предпочитаем удалить детей и заново вставить их в Отца (новое, старое не имеет значения) вместе с любыми другими обновлениями, которые отец может иметь в любом его другие простые поля) Итак ... для того, чтобы это работало, удалите дочерние элементы (внутри транзакции), вызвав childrenList.clear() (не перебирайте дочерние элементы и удалите каждого с некоторым значением childDAO.delete(childrenList.get(i).delete())) и установив @OneToMany(cascade = CascadeType.XXX ,orphanRemoval=true) на стороне Отца Объект. Затем обновите отца (папа DAO.update (папа)). (Повторите эти действия для каждого объекта отца). В результате у детей обрывается связь с отцом, а затем они удаляются из системы как сироты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...