Подтвердить что ты не робот

Org.hibernate.AssertionFailure: нулевой идентификатор в записи (не очищайте сеанс после возникновения исключения)

У меня есть спящий режим и приложение JSF2, идущее на сервер развертывания и внезапно бросающее org.hibernate.AssertionFailure: null id в качестве исключения. Я сразу же предоставил трассировку стека и код, но здесь сначала будут четыре важные проблемы:

  • Это происходит только на сервере развертывания (Jboss и MySql работает на Windows Sever 2008.) Это не происходит на моей машине разработки (Tomcat и MySql работает на Windoes 7 Pro), а также не в промежуточной среде ( Jboss и MySql, работающие на Linux.)

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

  • Ошибка происходит только время от времени. Если я перезапущу Jboss, он уйдет, но через некоторое время вернется. Кроме того, он несовместим, по некоторым щелчкам он там, на других это не так. Даже когда он попадает, когда я делаю простое обновление страницы, он возвращает штраф.

  • Я использую c3p0 (ниже)

Любая идея, что происходит?

Детали кода:

Это происходит на адресном объекте. Здесь полный hbm:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.idex.auctions.model">
<class name="Address" table="address" lazy="true">
  <id name="addressID" column="AddressID">
        <generator class="native"/>            
  </id>

  <property name="street" column="street"/> 
  <property name="city" column="city"/> 
  <property name="zip" column="zip"/> 
  <property name="state" column="state"/> 
  <property name="region" column="region"/> 
  <property name="country" column="country"/> 

  <many-to-one name="user" 
       class="com.idex.auctions.model.User" 
       column="userid" 
       unique="true" 
       cascade="save-update"/>
 </class> 
</hibernate-mapping>

Класс Java прямолинейный:

public class Address implements Serializable {
private static final long serialVersionUID = 7485582614444496906L;

private long addressID;
private String street;
private String city;
private String zip;
private String state;
private String region;
private String country;
private User user;

public Address() {

}
public long getAddressID() {
    return addressID;
}
public void setAddressID(long addressID) {
    this.addressID = addressID;
}
public String getStreet() {
    return street;
}
public void setStreet(String street) {
    this.street = street;
}
public String getCity() {
    return city;
}
public void setCity(String city) {
    this.city = city;
}
public String getZip() {
    return zip;
}
public void setZip(String zip) {
    this.zip = zip;
}
public String getState() {
    return state;
}
public void setState(String state) {
    this.state = state;
}
public String getRegion() {
    return region;
}
public void setRegion(String region) {
    this.region = region;
}
public String getCountry() {
    return country;
}
public void setCountry(String country) {
    this.country = country;
}
public User getUser() {
    return user;
}
public void setUser(User user) {
    this.user = user;
}

}

Конфигурация c3p0:

<property name="hibernate.c3p0.acquire_increment">1</property> 
<property name="hibernate.c3p0.idle_test_period">1000</property> 
<property name="hibernate.c3p0.max_size">20</property>  
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

Используемые версии

hibernate3.jar

c3p0-0.9.1.2.jar

myfaces-api-2.1.4.jar

myfaces-impl-2.1.4.jar

mysql-connector-java-5.1.20-bin.jar

Полный стек

org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry 
    (don't flush the Session after an exception occurs)
org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(
                                          DefaultFlushEntityEventListener.java:78)
org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(
                                          DefaultFlushEntityEventListener.java:187)
org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(
                                          DefaultFlushEntityEventListener.java:143)
org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(
                                          AbstractFlushingEventListener.java:219)
org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(
                                          AbstractFlushingEventListener.java:99)
org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(
                                          DefaultAutoFlushEventListener.java:58)
org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:997)
org.hibernate.impl.SessionImpl.list(SessionImpl.java:1142)
org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
com.idex.auctions.manager.DatabaseManager.getAllObjects(DatabaseManager.java:464)
com.idex.auctions.ui.NavBean.gotoHome(NavBean.java:40)
sun.reflect.GeneratedMethodAccessor350.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:735)
javax.el.BeanELResolver.invoke(BeanELResolver.java:467)
javax.el.CompositeELResolver.invoke(CompositeELResolver.java:246)
org.apache.el.parser.AstValue.getValue(AstValue.java:159)
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression.getValue(
                                          ContextAwareTagValueExpression.java:96)
javax.faces.component._DeltaStateHelper.eval(_DeltaStateHelper.java:246)
javax.faces.component.UIOutcomeTarget.getOutcome(UIOutcomeTarget.java:50)
org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils.getOutcomeTargetHref(
                                          HtmlRendererUtils.java:1542)
org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.renderOutcomeLinkStart(
                                          HtmlLinkRendererBase.java:908)
org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.encodeBegin(
                                          HtmlLinkRendererBase.java:143)
javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:502)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:744)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:758)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:758)
org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(
                                    FaceletViewDeclarationLanguage.java:1900)
org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:285)
com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(
                                    PrettyViewHandler.java:163)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
org.apache.myfaces.tomahawk.application.ResourceViewHandlerWrapper.renderView(
                                    ResourceViewHandlerWrapper.java:93)
com.idex.auctions.ui.CustomViewHandler.renderView(CustomViewHandler.java:98)
org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:115)
org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:126)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:118)
4b9b3361

Ответ 1

Исключение:

org.hibernate.AssertionFailure: нулевой идентификатор в записи (не очищайте сеанс после возникновения исключения)

Сообщает нам, что исключение сеанса произошло до, где выбрано это org.hibernate.AssertionFailure.

Точнее, org.hibernate.AssertionFailure вызывается, когда происходит session.flush(), а не точка, в которой произошла ошибка.

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

Ищите другие возможные точки ошибки: A save() или saveOrUpdate() возможно пытается сохранить объект с полем null, где в стол, столбец NOT NULL?


Совет: Чтобы помочь в отладке, попробуйте добавить session.flush() после каждого взаимодействия с объектом Session (например, session.save(obj), session.merge(obj) и т.д.), Это, надеюсь, приведет к тому, что org.hibernate.AssertionFailure произойдет раньше, ближе к тому, где реальная проблема имеет место. (Конечно, после отладки удалите те session.flush().)


В моем случае исключение real происходило внутри блока try/catch {}, где catch подавляло исключение (не ревертировало или не предупредило меня об этом).

Ответ 2

Я бы поставил для проблемы concurrency, но это может произойти на разных уровнях:

Помимо этих потенциальных источников проблем, я бы удалил c3p0 (возможно, просто слухи...), поскольку ваш стек уже предоставляет DataSource пул соединений, интегрированный с менеджером транзакций.

Ответ 3

Ответ: @asdcjunior ответил правильно. Что-то случилось до того, как будет выброшено исключение.

В таких ситуациях (часто бывает, когда вы используете единую транзакцию для одного теста - например, аннотация @Transaction), я вызываю метод:

session.clear()

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

Пример потока:

  • вставить объект назначения (отношение "многие ко многим" с ограничением, которое может содержать только одно назначение) → все нормально
  • вставить один и тот же объект присваивания еще раз → все в порядке, контроллер в этом случае возвращает какое-то неправильное исключение запроса, под капотом Spring выдает IntegrityViolationException → в тесте все выглядит нормально
  • получить репозиторий и выполнить findAll(). size(), чтобы проверить количество существующих назначенных, чтобы убедиться, что у нас есть только одно назначение → выбрано указанное исключение; /what happend? на сеансе есть все еще грязный объект, обычно сеанс будет уничтожен (ошибка возврата контроллера), но здесь мы имеем следующие утверждения для проверки относительно базы данных, поэтому решение здесь является дополнительным session.clear() перед последующим выполнением метода db

Пример правильного потока:

  • вставить объект присваивания
  • вставить тот же объект назначения
  • session.clear()
  • получить репозиторий и выполнить findAll(). size()

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

Ответ 4

Вероятно, вы сталкиваетесь с некоторой ошибкой Hibernate. (Я бы рекомендовал обновить, по крайней мере, Hibernate 3.3.2.GA.)

Между тем, Hibernate лучше, когда ваш идентификатор является нулевым, поэтому Hibernate всегда может отличить новый объект, который еще не был сохранен в базе данных, и тот, который уже находится в базе данных. Изменение типа addressID от long до long, вероятно, обойдется с проблемой.

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

Ответ 5

Я столкнулся с этой проблемой Я просто добавляю блок try catch и в блоке catch я написал seesion.clear(); теперь я могу приступить к записи остальных записей в базе данных.

Ответ 6

Проблема потока:

  1. Вы создаете новый временный экземпляр объекта (здесь экземпляр Address)
  2. Вы сохраняете его в базе данных (используя сохранение, слияние или сохранение в Hibernate Session/JPA EntityManager)
  3. Поскольку идентификатор сущности генерируется базой данных, hibernate должен инициировать вставку базы данных (сбрасывает сеанс) для получения сгенерированного идентификатора.
  4. Операция вставки вызывает исключение (или любое незавершенное незаполненное изменение в сеансе)
  5. Вы перехватываете исключение (не распространяя его) и возобновляете поток выполнения (в этот момент сеанс по-прежнему содержит необсуждаемый экземпляр без идентификатора, проблема в том, что в hibernate кажется, что экземпляр считается управляемым, но экземпляр поврежден как управляемый объект должен иметь идентификатор)
  6. Вы достигаете конца своей единицы работы, и сеанс автоматически сбрасывается перед фиксацией текущей транзакции, сбой сбоя с ошибкой подтверждения, так как сеанс содержит поврежденный экземпляр

У вас есть много возможных способов уменьшить эту ошибку:

  • Самый простой и в спящем режиме означает "не очищать сессию после возникновения исключения", т.е. немедленно отказаться и откатить текущую транзакцию после персистентного исключения.
  • Вручную удалить (JPA: отсоединить) поврежденный экземпляр от сеанса после обнаружения ошибки (в точке 5, но если ошибка была вызвана другим ожидающим изменением вместо самой вставки объекта, это будет бесполезно)
  • Не позволяйте базе данных обрабатывать генерацию идентификатора (используйте UUID или систему генерации распределенного идентификатора, в этом случае при окончательном сбрасывании будет выдана настоящая ошибка, предотвращающая сохранение нового экземпляра вместо сбоя подтверждения гибернации)

Ответ 7

Это не связано с исполняемым запросом. Это просто запускает флеш. В этот момент Hibernate пытается присвоить идентификатор объекту и по какой-то причине, по-видимому, потерпел неудачу.

Не могли бы вы попробовать изменить класс генератора:

<generator class="identity"/>

Посмотрите, если это имеет значение. Также вы убедились, что в развернутой базе данных есть правильный автоинкрементный столбец, настроенный в таблице?

Похоже, что ваш вопрос похож на на этот.

Ответ 8

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

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

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

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

Ответ 9

Изменение класса генератора:

<generator class="identity" />

к

<generator class="assigned" />

Ответ 10

org.hibernate.AssertionFailure: нулевой идентификатор в записи (не очищайте сеанс после возникновения исключения)

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

Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry '' for key
'Index_schools_name'

Это исключение, однако, маскировалось, потому что hibernate пытался зафиксировать сеанс, даже несмотря на то, что создание не удалось. Когда созданный не удалось, идентификатор не был установлен, следовательно, ошибка assert. В трассировке стека мы увидели, что спящий режим совершает:

at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit
(HibernateTransactionManager.java:480)

Он должен был отменить сеанс, не совершая его. Это оказалось проблемой с нашей конфигурацией отката. Мы используем старые конфигурации XML, и путь исключения был неправильным:

<prop key="create*">PROPAGATION_REQUIRED,-org.x.y.LocalException</prop>

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

// NOTE: that the rollbackFor exception should match the throws (or be a subclass)
@Transactional(rollbackFor = LocalException.class)
public void create(Entity entity) throws AnotherException {

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

Еще одна морщина для этого заключалась в том, что когда hibernate выбрасывал AssertionFailure, он удерживал транзакционную блокировку в MySQL, которая затем должна была быть убита вручную. См.: fooobar.com/questions/92912/...

Ответ 11

У меня тоже такое исключение, в файле конфигурации hibernate:

<property name="operateType" type="java.lang.Integer">
        <column name="operate_type" not-null="true" />
 </property>

при передаче значения null у объекта, возникновения исключения

 "org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry",

Я думаю, причина в том, что Hibernaye будет проверять свойство "не-null" , поэтому удалить свойство "не-null" или установить "не-null" для "false", разрешит проблему.

Ответ 12

Иногда это происходит, когда длина строки больше, чем разрешено БД.

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

Поэтому, если у вас есть аннотация Column в поле String сущности с заданной длиной, а фактическое значение больше этой длины, генерируется указанное выше исключение.

Ссылка: https://developer.jboss.org/thread/186341?_sscc=t

Ответ 13

org.hibernate.AssertionFailure: нулевой идентификатор в записи (не очищайте сессию после возникновения исключения)

Вы получаете эту ошибку при использовании метода save, если вы setCreatedBy(1); setModifiedBy(1); setCreationDate(); setChangeDate(); историю версий пользовательской активности и пытаетесь установить следующие значения setCreatedBy(1); setModifiedBy(1); setCreationDate(); setChangeDate(); setCreatedBy(1); setModifiedBy(1); setCreationDate(); setChangeDate(); } Вы получите вышеуказанную ошибку, чтобы решить эту проблему, вам нужно создать следующие столбцы в таблице.

Created_By Modified_By Creation_Date Change_Date если вы получаете ту же ошибку, когда метод Update решает эту проблему. Просто вам нужно изменить метод Update() на метод merge(), который, я надеюсь, помог вам.

Ответ 14

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

public final Session getCurrentSession()  
{
    Session session = sessionFactory.getCurrentSession();
    session.setFlushMode(FlushMode.MANUAL);
    return session;
}

Затем я получил еще одно исключение, которое объяснило мне, что произошло на самом деле. Затем я сделал откат транзакции в блоке catch моего метода create. И это помогло мне.

Ответ 15

Я сталкиваюсь с той же ошибкой, когда делаю session.getCurrentSession.refresh(entity), для меня это больше похоже на ошибку, а не на проблему с моим кодом. Я получаю эту ошибку в модульном тесте, когда пытаюсь обновить сущность в начале теста, и эта сущность создается в настройках теста (с пометкой junit @Before). Странно то, что я создаю 3 объекта из одного и того же класса со случайными данными в одно и то же время и таким же образом в настройке, и я могу обновить первые два созданных, но обновление завершается неудачно для последнего. Так, например, если я создаю 3 объекта User в настройках теста, я могу обновить user1 и user2, и для user3 произойдет сбой. Я смог решить эту проблему, добавив session.flush() в конце кода, который создает объект в настройке. Я не получаю никаких ошибок, и я должен, но я не могу объяснить, зачем нужен дополнительный сброс. Также я могу подтвердить, что сущности на самом деле находятся в тестовой БД, даже без сброса, потому что я могу запросить их в тесте, но все еще не удается обновить (сущность) метод.

Ответ 16

Откат транзакции в блоке catch