2009-05-22 5 views
3

나는 트리를 데이터베이스로 업데이트하는 프로세스를 가지고 있으며, 그렇게함으로써 중복 엔티티를 검사하기 위해 읽기를 수행한다. 스택 추적을 통해 파고Hibernate는 find-not-null이 아닌 에러로 flush를 호출한다.

org.hibernate.PropertyValueException: not-null property references a null or transient value

, 나는에 uniqueResult()가 플러싱 것을 볼 : 나는 중간에이 과정을 통해)를 criteria.uniqueResult를 (을하려고 것을 찾는거야

다음과 같은 오류가 발생합니다 세션에서 아직 데이터베이스로 이동할 준비가되지 않은 업데이트를 수행하려고합니다.

at org.hibernate.engine.Cascade.cascade(Cascade.java:153) 
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154) 
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145) 
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) 
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58) 
at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:996) 
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1589) 
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306) 
at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:328) 
at com.inversion.dal.BaseDAO.findUniqueByCriterion(BaseDAO.java:59) 

내가 여기에 뭔가 잘못 설정 했습니까?

도움을 주시면 감사하겠습니다.

마티

답변

3

최대 절전 모드 개체를 저장해야합니다. select를 실행하면 최대 절전 모드가 변경 사항을 플러시합니다. 이렇게하면 select가 올바른 결과를 반환합니다.

FlushMode를 FlushMode.AUTO 이외의 것으로 설정하면이 동작을 방지 할 수 있습니다. 그러나 오류는 코드에서 지속되거나 업데이트되도록 최대 절전 모드로 전환하는 불완전한 개체를 전달합니다. 그래서 올바른 해결책은 객체가 완료 될 때 객체를 나중에 최대 절전 모드로 전달하는 것입니다.

+0

불완전한 객체를 hibernate로 전달하는 것은 null 제약 조건 위반의 좋은 후보이다. 이미 세션에있는 항목의 수정과 관련하여 이러한 오류를 유발할 수있는 많은 코드 경로가 있으므로 항상 명확하지는 않다. 오류가 발생합니다. – Jherico

2

이 예외를 수정하려면 세션 개체에서 자동 비우기를 해제하십시오.

Session s; 
// if you're doing transactional work 
s.setFlushMode(FlushMode.COMMIT); 
// if you want to control flushes directly 
s.setFlushMode(FlushMode.MANUAL); 

그러나 이것은 사용자의 실수가 아닙니다. 코드의 앞부분에있는 메모리 개체가 자동 플러시 중에 DB에 유지하려고하는 잘못된 상태가됩니다.

+0

@Transactional (readOnly = false) 트랜잭션 경계를 표시하기 위해 주석을 사용하고 있습니다. 나는 이것이 내 코드 내에서 수동으로 처리되는 것이 아니라 경계를 처리하는 선호 된 방법이라고 생각했다. 또한 엔티티는 유효하지 않은 상태이지만 아직 커밋되지 않았습니다. 절전 모드는 SELECT 중에 자체적으로 그렇게합니다. 왜? –

+1

트랜잭션에 있다고해서 SQL이 데이터베이스에 대해 실행되지 않는다는 의미는 아닙니다. FlushMode는 트랜잭션이 커밋되지 않을 때 SQL이 실행될 때를 제어합니다. 데이타베이스와 관련하여 유효하지 않은 상태의 오브젝트를 작성하려는 경우 Jherico가 제안하는 방식으로 나중에 플러시를 연기해야 ​​할 수도 있습니다. –

0

나는이 문제의 최하점을 찾으려고 여러 번 머리카락을 뽑았습니다. 문제는 문제의 근본 원인을 찾기가 너무 어렵다는 것입니다.

당신이 당신의 순발력에 근접하는 경우

는 또한 새로운 세션에서 지원하는 쿼리를 같은 findAll을 실행할 수 있습니다 종료 : 대부분의 경우에 나를 위해 문제를 우회 보통 한

Domain.withNewSession { session -> ... } 

.

관련 문제