2014-11-14 2 views
4

"긴 예상 잘못된 유형의 ID를 제공는, 클래스 DelayedPostInsertIdentifier있어"최대 절전 모드 짧은에서 예외

내가 저장 한 부모의 일대 세트에 새로운 (저장되지 않은) 엔티티를 추가하려고, 상위 엔티티에서 Merge를 호출 한 후 다음 예외가 발생합니다.

com.test.Child 클래스에 잘못된 유형의 ID가 제공되었습니다. 예상 : 클래스 java.lang.Long의, 저도 같은 문제를 나타내는 표를 발견했습니다 org.hibernate.action.internal.DelayedPostInsertIdentifier

클래스 을 가지고 : https://hibernate.atlassian.net/browse/HHH-2382 그것은 거부 훨씬 도움이되지 않습니다 내 질문과 함께.

아무도이 문제에 직면 했습니까? 누구나 문제의 원인과 가능한 해결책을 지적 할 수 있습니까? 세부

문제 :

나는 두 개의 클래스가 있습니다 공용 클래스의 부모가 BASEMODEL 직렬화 { 개인 긴 ID를 구현 확장을, 비공개 자녀 설정; }

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에 잘못된 유형의 ID를 제공했습니다. 예상 됨 : 클래스 java.lang.Long, 클래스를 얻습니다. org.hibernate.action.internal.DelayedPostInsertIdentifier at org.hibernate.event.internal.DefaultLoadEventListener.onLoad (DefaultLoadEventListener.java:134) at org.hibernate.internal.SessionImpl .fireLoad org.hibernate.type.EntityType.resolveIdentifier (EntityType.java:648)에서 org.hibernate.internal.SessionImpl.internalLoad (SessionImpl.java:1019)에서 (SessionImpl.java:1092) 조직에서 .hibernate.type.EntityType.resolve (EntityType.java:468) at org.hibernate.type.EntityType.replace (EntityType.java:325) at org.hibernate.type.CollectionType.replaceElements (CollectionType.java:517)) at org.hibernate.type.Col org.hibernate.event.internal.DefaultMergeEventListener.copyValues에서 org.hibernate.type.TypeHelper.replace (TypeHelper.java:177) (DefaultMergeEventListener.java:372) 에서 lectionType.replace (CollectionType.java:667)에서 org.hibernate.event.internal에서 org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent org.hibernate.event.internal.DefaultMergeEventListener.onMerge (DefaultMergeEventListener.java:157)에서 (DefaultMergeEventListener.java:184) .DefaultMergeEventListener.onMerge (기본 모니터 이벤트 리스너.java : 898) at org.hibernate.internal.SessionImpl.merge (SessionImpl.java:902) at com.test.DAOFacade.saveObject (DAOFacade.java:273) com.test.Test.testSaving (MemcachedTest. 자바 : 나는 시간과 모든 프로세스 디버깅 봤는데

<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> 

:

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(); 
} 

하이버 네이트 매핑은 다음과 같습니다 : 99)

DaoFacade.save 방법은 다음과 같은 방법을 찾습니다 ES는 최대 절전 모드에서 correclty 갈 보이지만, 사실은 다음과 같은 문제에 이르게 : 병합하는 동안

  • 이 반복 필드시, 저장되지 않은 "두 번째"아이가 발견 입니다.
  • "두 번째"하위가 삽입 용으로 표시되고 삽입 쿼리가 준비되어 QueryQueue에 삽입됩니다.
  • 머지 프로세스를 계속하는 동안 어떤 순간에 최대 절전 모드가 "두 번째"자식을로드하려고 시도 중입니다.
  • 그러나 아직 삽입되지 않았으므로 Excpetion이 발생했습니다.

답변

1

또한이 문제가 발생했습니다. saveOrUpdate 메소드가 트랜잭션을 시작하지 않는 것에 주목하십시오. 이 문제를 해결하려면 session.update 또는 session.saveOrUpdate를 호출 한 후 트랜잭션을 시작하고 트랜잭션을 커밋해야합니다.

업데이트이처럼 될 saveOrUpdate 방법 :

thread
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(); 
    } 

} 

가 문제의 해결책이 나에게 힌트를주고 당신 될 saveOrUpdate 방법은 누락 된 트랜잭션을 확인합니다.

+0

우리가 높은 수준에서 사용하기 때문에 우리는이 트랜잭션을 사용하지 마십시오 : @arjaynacion에 의해 제안 저장이 문제를 해결 수행하는 방법에 @Transactional 주석을 추가하면 우리는 업데이트하고 작성해야합니까 하나의 트랜잭션 내에서 여러 유형의 여러 엔티티. 그리고 때때로 우리는 중요하지 않은 엔티티 (예외가 발생한 곳)에 트랜잭션을 사용하지 않습니다. 아마 그것은 그것이 문제의 근원이라는 것입니다. 그리고 우리는 어떤 메커니즘을 생성하고 필요할 때만 트랜잭션을 생성해야합니다. –

+0

@DmitriiSemenov, 상위 레벨에서 트랜잭션을 사용하고 있다고 할 때, 트랜잭션 관리 프레임 워크 (예 : Spring-Spring-tx)를 사용하고 있다는 것을 의미합니까? 왜 트랜잭션을 만들지 않고 saveOrUpdate 또는 update 메소드를 호출 할 수 있는지 말해 줄 수 있습니까? – arjaynacion

0

나는 Hibernate 4.2.15와 Spring을 사용하여 같은 문제가 발생했다.

@Transactional 
@NotNull 
protected S save(@NotNull S entity) 
{ 
    return getDao().save(entity); 
} 
관련 문제