2014-11-14 5 views
4

Короче:Hibernate «При условии идентификатора неправильного типа ожидаемого Long, получил класс DelayedPostInsertIdentifier» исключение

Когда я пытаюсь добавить новый (несохраненный) Entities на один-ко-многим набор сохраненного родителя, после вызова Merge на родительском объекте, я получаю следующее исключение:

Предоставлено id неправильного типа для класса com.test.Child. Ожидаемый: класс java.lang.Long, есть класс org.hibernate.action.internal.DelayedPostInsertIdentifier

Я нашел билет, представляющий тот же вопрос: https://hibernate.atlassian.net/browse/HHH-2382 Он был отвергнут и не очень помогает с моим вопросом.

Неужели кто-нибудь сталкивался с этой проблемой? Может ли кто-нибудь указать источник проблемы и возможное решение?

Проблема в деталях:

У меня есть два класса: общественного класс Parent распространяется BaseModel реализует Serializable { частных длинного идентификатора; частные дети; }

public class Child extends BaseModel implements Serializable { 
    private long id; 
    private String value; 
} 

Я пытаюсь выполнить следующий код:

Parent parent = new Parent(); 
parent.setChildren(new HashSet<Child>()); 

Child child = new Child(); 
child.setValue("First"); 
parent.getChildren().add(child); 

parent = daoFacade.save(parent); 

child = new Child(); 
child.setValue("Second"); 
parent.getChildren().add(child); 

parent = daoFacade.save(parent); 

И после вызова метода сохранения во второй раз, я получаю следующее исключение:

org.hibernate.TypeMismatchException : Предоставлен идентификатор неправильного типа для класс com.text.Child. Ожидаемый: класс java.lang.Long, есть класс org.hibernate.action.internal.DelayedPostInsertIdentifier в org.hibernate.event.internal.DefaultLoadEventListener.onLoad (DefaultLoadEventListener.java:134) в org.hibernate.internal.SessionImpl .fireLoad (SessionImpl.java:1092) на org.hibernate.internal.SessionImpl.internalLoad (SessionImpl.java:1019) на org.hibernate.type.EntityType.resolveIdentifier (EntityType.java:648) в орг .hibernate.type.EntityType.resolve (EntityType.java:468) в org.hibernate.type.EntityType.replace (EntityType.java:325) в org.hibernate.type.CollectionType.replaceElements (CollectionType.java:517)) по адресу org.hibernate.type.Col lectionType.replace (CollectionType.java:667) на org.hibernate.type.TypeHelper.replace (TypeHelper.java:177) при org.hibernate.event.internal.DefaultMergeEventListener.copyValues ​​(DefaultMergeEventListener.java:372) на org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent (DefaultMergeEventListener.java:184) на org.hibernate.event.internal.DefaultMergeEventListener.onMerge (DefaultMergeEventListener.java:157) на org.hibernate.event.internal .DefaultMergeEventListener.onMerge (DefaultMergeEventListener.java:76) at org.hibernate.internal.SessionImpl.fireMerge (SessionImpl.java:914) at org.hibernate.internal.SessionImpl.merge (SessionImpl.java: 898) на org.hibernate.internal.SessionImpl.merge (SessionImpl.java:902) на com.test.DAOFacade.saveObject (DAOFacade.java:273) на com.test.Test.testSaving (MemcachedTest. Java: 99)

метод DaoFacade.save выглядит следующим образом:

public void saveOrUpdate(T obj) { 
    Session session = getSession(); 

    BaseModel model = (BaseModel) obj; 
    if (model.isNew()) { 
     T merged = (T)session.merge(obj); 
     session.update(merged); 
    } else { 
     session.saveOrUpdate(obj); 
    } 
    session.flush(); 
} 

Hibernate отображения являются:

<class name="Parent" table="PARENT"> 
    <id name="id" column="id" unsaved-value="0"> 
     <generator class="native"/> 
    </id> 
    <set name="children" inverse="false" lazy="false" cascade="all"> 
     <cache usage="read-write" /> 
     <key column="LINK_ID"/> 
     <one-to-many class="Child"/> 
    </set>  
</class> 

<class name="Child" table="CHILD"> 
    <cache usage="read-write" /> 

    <id name="id" column="id" unsaved-value="0"> 
      <generator class="native"/> 
     </id> 

     <property name="value" type="string" column="VALUE" not-null="true" lazy="false"/>  
</class> 

Я отладки в течение нескольких часов и всего процесса эс, кажется, идет correclty в спящем режиме, но на самом деле это приводит к следующей задаче:

  • Во время слияния, при переборе полех, несохраненный «Второй» Ребенок найдено.
  • «Второй» Ребенок помечен для вставки, Вставка запроса подготовлена ​​и помещается в QueryQueue.
  • Продолжая процесс слияния, Спящий режим в какой-то момент пытается загрузить «Второго» Ребенка
  • Но он еще не вставлен, а Excetchion поднят.

ответ

1

Я также столкнулся с этой проблемой. Обратите внимание, что метод saveOrUpdate не запускает транзакцию. Решение этого - начать транзакцию и обязательно совершить транзакцию после вызова session.update или session.saveOrUpdate.

Обновить ваш метод saveOrUpdate так:

public void saveOrUpdate(T obj) { 
    Session session = getSession(); 
    Transaction tx = null; 
    try { 
     tx = session.beginTransaction(); 
     BaseModel model = (BaseModel) obj; 
     if (model.isNew()) { 
     T merged = (T)session.merge(obj); 
     session.update(merged); 
     } else { 
     session.saveOrUpdate(obj); 
     } 
     tx.commit(); 
    } catch (Exception ex) { 
     tx.rollback(); 
    } 

} 

Это thread дал мне намек на решение вашей проблемы и ваш метод saveOrUpdate проверяет отсутствующую транзакцию.

+0

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

+0

@ DmitriiSemenov, когда вы говорите, что используете транзакции на более высоком уровне, вы имеете в виду, что вы используете какую-то структуру управления транзакциями (например, Spring-spring-tx)? вы можете сказать мне, почему вы бы назвали метод saveOrUpdate или update без создания транзакции? – arjaynacion

0

У меня была такая же проблема с использованием Hibernate 4.2.15 и Spring. Добавление @Transactional аннотацию к методу исполняющей спасбросок решить эту проблему, как это было предложено @arjaynacion:

@Transactional 
@NotNull 
protected S save(@NotNull S entity) 
{ 
    return getDao().save(entity); 
}