2010-04-30 2 views
92

Я получаю следующую спящую ошибку. Я могу определить функцию, которая вызывает проблему. К сожалению, в функции есть несколько вызовов БД. Я не могу найти строку, которая вызывает проблему, поскольку hibernate завершает сеанс в конце транзакции. Ниже приведенная ошибка спящего режима выглядит как общая ошибка. В нем даже не упоминается, какой Bean вызывает проблему. Кто-нибудь знаком с этой спящей ошибкой?Hibernate - пакетное обновление возвратило неожиданный счет строки из обновления: 0 фактическое количество строк: 0 ожидаемых: 1

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) 
+0

Спасибо @Peter Mortensen. Я обновил свою электронную почту. – Sujee

+0

У меня такая же проблема. Это не большая проблема, поскольку это происходит очень редко. Использование show_sql нецелесообразно, так как для воспроизведения этого поведения требуются миллионы транзакций. Однако, поскольку это происходит неоднократно во время системного теста, который я запускаю (который имеет gazillions транзакций), я подозреваю, что есть определенная причина. –

ответ

35

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

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

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

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

+18

hibernate.show_sql> Я бы скорее посоветовал установить категорию журнала org.hibernate.SQL на DEBUG. Таким образом, вам не нужно изменять конфигурацию спящего режима только для ведения журнала. – Thierry

+0

Использование «show_sql» может быть очень многословным и практически невозможным в производстве. Для этого я изменил предложение catch в строке 74 класса BatchingBatcher, чтобы напечатать инструкцию с помощью ps.toString(), чтобы иметь только инструкцию, которая имеет проблему. – Orden

38

У меня такое же исключение при удалении записи по идентификатору, который вообще не существует. Поэтому проверьте, что запись, которую вы обновляете/Фактически существует в DB

+8

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

+0

Это решило мою проблему. Запись не существовала, и моя служба вызывала метод updateAll(), в то время как на самом деле требовалось вызвать метод createOrUpdateAll(). Благодарю. –

+2

так как решить проблему? Если я получу запись, а затем удалю ее; но если система уже удаляет его перед удалением, другое, мое приложение будет генерировать исключение. – Stony

6

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

4

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

1

это случается, когда вы пытаетесь удалить то же самое bject, а затем снова обновить тот же объект, что и после удаления

session.clear();

7

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

SET NOCOUNT ON; 
+1

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

+2

+1 Это была моя проблема. Я использовал postgresql, поэтому вам нужно было использовать аннотацию @SQLInsert, чтобы отключить проверку количества строк: http://www.technology-ebay.de/the-teams/mobile-de/blog/postgresql-table-partitioning-hibernate. html – s1mm0t

13

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

3

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

5

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

В файле сопоставления hibm hibm для master, для объекта с настройкой типа набора, добавлен cascade="save-update", и он отлично работал.

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

30

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

Если вы установите значение свойства Id явно, это приведет к ошибке выше. Проверьте это, чтобы избежать этой ошибки. или Это ошибка шоу, когда вы упоминаете в файле отображение генератор поля = «родные» или «дополнительные» и в базе данных в таблице отображается не auto_incremented Решения: Перейти к вашей базе данных и обновить таблицу, чтобы установить auto_increment

+1

Абсолютно верно. Это должен быть правильный ответ. Спасибо @ Rēda Biramanē –

+0

* Однако вы можете установить значение ID равным «0», а затем Hibernate будет свободно перезаписывать его. – forresthopkinsa

0

Я столкнулся с этой проблемой, когда я начинал вручную и совершал транзакции внутри метода, аннотированного как @Transactional. Я исправил проблему, обнаружив, что активная транзакция уже существует.

//Detect underlying transaction 
if (session.getTransaction() != null && session.getTransaction().isActive()) { 
    myTransaction = session.getTransaction(); 
    preExistingTransaction = true; 
} else { 
    myTransaction = session.beginTransaction(); 
} 

Тогда я позволил весне справиться с совершением сделки.

private void finishTransaction() { 
    if (!preExistingTransaction) { 
     try { 
      tx.commit(); 
     } catch (HibernateException he) { 
      if (tx != null) { 
       tx.rollback(); 
      } 
      log.error(he); 
     } finally { 
      if (newSessionOpened) { 
       SessionFactoryUtils.closeSession(session); 
       newSessionOpened = false; 
       maxResults = 0; 
      } 
     } 
    } 
} 
2

Это случилось со мной тоже, потому что у меня был мой идентификатор, как долго, и я получал с точки зрения значение 0, и когда я пытался сохранить в базе данных я получил эту ошибку, то я установил его установите id в значение null.

2

Это происходит, когда вы объявили о JSF Managed Bean в качестве

@RequestScoped; 

когда вы должны объявить как

@SessionScoped; 

С уважением;

5

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

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 // означает, что запись не установлено обновление
обновление: 0 // означает, что запись не нашел так ничего обновление
ожидается: 1 // означает, что ожидается, по крайней мере 1 запись с ключом в db-таблица.

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

+0

Привет @ParagFlume, я получил ту же ошибку «Пакетное обновление возвратило неожиданный ряд строк из обновления: 0 фактическое количество строк: 0 ожидаемых: 1 «когда я пытаюсь выбрать один объект из моей базы данных, проблема существует только в любой продукции, есть ли у вас какая-либо идея о том, как решить эту проблему, я в критической ситуации. С уважением ! – James

+0

Я думаю, что запрос не нашел записи в db, он ожидает найти одну запись в db, которую он пытается обновить. вы можете проверить вручную/запрос-браузер, если запись действительно существует на db. – ParagFlume

+0

да запись существует, но моя проблема в том, почему hibernate пытается обновить, я просто использую услугу select, чтобы получить объект из базы данных! – James

1

Я получил эту ошибку, когда попытался обновить объект с идентификатором, которого не было в базе данных. Причиной моей ошибки было то, что я вручную назначил свойство с именем «id» на JSON-представление клиента на стороне клиента, а затем при десериализации объекта на стороне сервера это свойство «id» заменило бы переменную экземпляра (также называемый «id»), который должен был генерировать Hibernate. Поэтому будьте осторожны с именами коллизий, если вы используете Hibernate для генерации идентификаторов.

0

Это произошло, если вы изменили что-то в наборе данных, используя собственный SQL-запрос, но сохраняемый объект для того же набора данных присутствует в кеше сеанса. Использовать session.evict (yourObject);

1

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

Фактически в моем приложении я получал объект базы данных для обновления. И, обновляя свои значения, я также по ошибке обновил его идентификатор и пошел дальше, чтобы обновить его и наткнулся на указанную ошибку.

Я использую hibernateTemplate для операций CRUD.

0

Hibernate кэширует объекты из сеанса. Если объект доступен и изменен более чем одним пользователем, тогда может быть выбрано org.hibernate.StaleStateException. Он может быть решен с помощью метода объединить/обновить объект перед сохранением или использованием блокировки. Больше информации: http://java-fp.blogspot.lt/2011/09/orghibernatestalestateexception-batch.html

0

После прочтения всех ответов не было найдено ни одного сообщения об обратном атрибуте спящего режима.

По моему мнению, вы должны также проверить в своих отношениях сопоставление: inverse ключевое слово правильно настроено. Обратное ключевое слово создано, чтобы определить, какая сторона является владельцем для поддержания отношений. Процедура обновления и вставки изменяется в соответствии с этим атрибутом.

Давайте предположим, что у нас есть две таблицы:

principal_table, middle_table

с соотношением один ко многим. Классы отображения гибернетита: Основные и Средние соответственно.

Категория Основная категория класс имеет набор средний объектов.Отображение файлов XML должен быть как следующее:

<hibernate-mapping> 
    <class name="path.to.class.Principal" table="principal_table" ...> 
    ... 
    <set name="middleObjects" table="middle_table" inverse="true" fetch="select"> 
     <key> 
      <column name="PRINCIPAL_ID" not-null="true" /> 
     </key> 
     <one-to-many class="path.to.class.Middel" /> 
    </set> 
    ... 

Как обратной установлено значение «истина», это означает, что класс «Средний» является владельцем отношения, так что главный класс НЕ ОБНОВЛЕНИЕ отношения.

Так процедура обновления может быть реализована следующим образом:

session.beginTransaction(); 

Principal principal = new Principal(); 
principal.setSomething("1"); 
principal.setSomethingElse("2"); 


Middle middleObject = new Middle(); 
middleObject.setSomething("1"); 

middleObject.setPrincipal(principal); 
principal.getMiddleObjects().add(middleObject); 

session.saveOrUpdate(principal); 
session.saveOrUpdate(middleObject); // NOTICE: you will need to save it manually 

session.getTransaction().commit(); 

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

0

Один из корпуса

SessionFactory sf=new Configuration().configure().buildSessionFactory(); 
Session session=sf.openSession(); 

UserDetails user=new UserDetails(); 

session.beginTransaction(); 
user.setUserName("update user agian"); 
user.setUserId(12); 
session.saveOrUpdate(user); 
session.getTransaction().commit(); 
System.out.println("user::"+user.getUserName()); 

sf.close(); 
0

Я получил эту ошибку, потому что я по ошибке отображается в ID столбец, используя Id(x => x.Id, "id").GeneratedBy.**Assigned**();

Устранена с помощью Id(x => x.Id, "id").GeneratedBy.**Identity**();

0

я столкнулся это исключение, и спящий режим был хорошо работает. Я попытался вставить вручную одну запись с помощью pgAdmin, здесь проблема стала очевидной. SQL insert query возвращает 0 insert. и есть триггерная функция, вызывающая эту проблему, поскольку она возвращает значение null. поэтому я должен только установить его для возврата нового. и, наконец, я решил проблему.

надежды, которые помогают любому телу.

0

Это также может случиться, когда вы пытаетесь сделать UPDATE a ПЕРВИЧНЫЙ КЛЮЧ.

1

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

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

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

0

Это происходит со мной, потому что мне не хватает идентификационной декларации в классе bean.

0

В моем случае возникла проблема с базой данных, так как одна из хранимых процедур потребляла весь процессор, что вызывало высокие времена ответа БД. Как только это было убито, проблема была решена.

0

Это происходит на самом деле, когда я не хранил объект в классе Entity Reference variable .. lik этот код: ses.get (InsurancePolicy.class, 101); После этого я сохранил объект в ссылочной переменной сущности, чтобы решить проблему для меня policy = (InsurancePolicy) ses.get (InsurancePolicy.class, 101); после этого я обновляю объект, и он отлично работает

+0

требует битное форматирование – Billa

Смежные вопросы

 Смежные вопросы