2012-04-15 1 views
6

나는 여기에 손실이 있으며, 아마도 Hibernate 전문 지식이 다른 영역보다 약하기 때문에 아마도 명백한 것이다.Hibernate가 기존 데이터를 마이 그 레이션하기위한 임베드 가능 클래스를 스왑 아웃

레거시 코드에는 최대 절전 모드 @Entity 클래스 Foo이 있습니다.

@Embeddable 
public class OldBar { 

    private String fooBar; 

    @Column(length = 10, nullable = false) 
    private String getFooBar() { 
    return fooBar; 
    } 

    @SuppressWarnings("unused") 
    private void setFooBar(String fooBar) { 
    this.fooBar = fooBar; 
    } 
} 

원래 문제는 내가 OldBar.fooBar 뭔가를 할 필요가 있다는 것입니다,하지만 :

private OldBar bar = new OldBar(); 

OldBar가 단일 열, foobar를 사용하는 @Embeddable 클래스 다음 속성 중 하나는 이것이다 독창적 인 디자인에는 제한이 있었고이 필드를 비공개로 설정하여 하위 클래스 화를 막았습니다. 따라서 다른 클래스 (NewBar)를 만들어야만 다른 필드를 액세스하고 비공개 필드에 액세스 할 수있었습니다.

private NewBar bar = new NewBar(); 

나는 내가 foobar 열에서 기존 데이터를 가지고 있기 때문에이 일을 원했고, : 나는 NewBarEmbeddable과 같은 @Column 지정을 가지고 있기 때문에, 내가 클래스 Foo의 필드를 교체 단지 수 있다고 생각 OldBar 대신 NewBar으로이 데이터를 투명하게 사용하고 싶습니다.

추적 로그를 통해 나는 의 기본 버전으로 생성자가 호출 될 때 예상대로 Foo()이 생성 된 것을 확인했습니다. 그러나 시간 코드 Foo.getBar()을 호출하면 어떤 이유로 barnull입니다! 나는 Hibernate가 어떤 이유에서 이것을 null으로 설정하고 있다고 가정한다. 그러나 최대 절전 모드가 foobar 컬럼에서 데이터를 읽고 NewBar의 인스턴스를 생성하는 이유는 무엇인가? OldBarNewBar 대신 넣으면 다시 작동하는 이유는 무엇입니까? 확실히 @Embeddable 클래스 중 어떤 클래스가 열에 매핑되는지는 데이터베이스 자체에 아무것도 없습니다.

업데이트 : 이것은 낯선 사람과 낯선 사람을 얻습니다. 때로는 코드를 밤새 사용하게하고 그 다음날 작동합니다! 아니면 다음 날에 작동하지 않습니다! 지금은 작동하지 않습니다 (즉, foobar 속성은 데이터베이스의 값 대신 null으로 설정 됨), 따라서 ExactCopyOfOldBar 클래스를 만들어 OldBar 대신 넣었습니다. 괜찮 았어! 따라서 NewBar으로 다시 전환합니다. 일시적인 변경 사항을 취소하기 만하면됩니다. 전에는 없었던 때에도 여전히 효과가있었습니다! Hibernate가 값을 직렬화하고 데이터베이스에서 가져 오지 않는 일종의 캐시가 있습니까? 이것은 매우 이상합니다.

업데이트 : 이제 더 이상 NewBar을 사용할 수 없습니다. OtherBar을 만듭니다.이 이름은 기본적으로 NewBar과 동일합니다. 단, 이름이 다르며 플러그를 꽂으면 올바르게 작동합니다. 포함 된 문자열을 올바르게 읽습니다. 다시 NewBar으로 전환하면 null이 다시 발생합니다. 무슨 일 이니?

Foo은 아주 간단하다, net.databinder.auth.hib.AuthDataApplication.getUser(String username) 통해로드되고 있음을

참고 : 나는 Foo (사용자) 테이블이 올바른 데이터를 단일 행을 가지고 또 다시 확인하고 한

return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass()) 
    .add(Restrictions.eq("username", username)).uniqueResult(); 

및 가장 중요한 것은 foobar 필드에 데이터가 있다는 것입니다. 왜 Hibernate는 nullfoobar 필드를 가지고 Foo을 돌려 주나요? NewBar에서 OtherBar으로 간단히 전환하면 다시 작동하기 시작하는 이유는 무엇입니까? 내가 하루 종일 방치 한 후 하루 종일 작동하고 일을 멈추는 이유는 무엇입니까?

+0

나는 이것이 사실 있으리라 믿고있어,하지만 당신은 그것을 말하지 않았다 : Foo.bar'는'@ Embedded'로 표시'있습니까? –

+0

@Tim Pote : 사실 이상하게도 원래의 (작동중인) 레거시 코드에서는'@ Embedded'라고 표시되지 않았습니다. 'OldBar'를'NewBar'로 변경했을 때'@ Embedded'의 유무에 관계없이 시도해 보았지만 차이는 없었습니다. –

+0

@ 팀 Pote : 나는 ... 최대 절전 모드 [문서] (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/) "그에서 배운 경우, 재산의 종류 @Embeddable로 주석 처리되고, @Embedded로 매핑됩니다. "기술적으로'@ Embedded' 부분은 선택 사항입니다. –

답변

1

이것은 대답 일 수 있습니다. 실제로 문제가 해결되는지 확인하기 위해 며칠을 기다려야 할 것입니다. 사실 두 부분이 있습니다.

먼저 전체 공개를 위해 내 NewBar 클래스는 실제로 AbstractBar의 하위 클래스였습니다. 나는 결국 임베드 바의 다른 유형을 가지고 싶어서가 아니라 NewBar 레벨에서 AbstractBar 수준에서 @Embeddable을 배치하고,뿐만 아니라 AbstractBar 수준에서 개인 foobar 필드를 배치했다. 재미있는 점은이 작업이 어느 정도 시간이 걸렸습니다. 그리고 제가 언급했듯이, 때때로 나는 그 다음날 돌아올 것이고 Hibernate는 foobar 필드를로드하지 않을 것입니다. 나는 왜 그것이 항상 작동하지 않거나 아무 시간도 일하지 않았다는 것을 이해하지 못한다. 나는 문제의 한 원인을 제거하기 위해이 계층 구조를 제거하려고 할 때 최대 절전 모드가이었다 보지 않았다, 그래서

둘째, 나는 AbstractBarNewBar을으로 융합하지만 AbstractBar에서 NewBar까지 @Embeddable을 가지고 잊었다 포함 할 수있는 클래스이며 @Embeddable 지정이없는 NewBar 필드에 문자열을로드하는 방법을 알지 못했습니다. (AN @Embeddable 주석과) OtherBar는 (아무 @Embeddable 주석) NewBar했다,하지만 이유입니다. 이 정도는 이해합니다. 왜 Hibernate는 필드로드 방법을 알 수 없다고 경고하지 않았지만, 나는 모른다.

그래서 당신이 클래스 오프 @Embeddable 주석을 왼쪽으로 한 경우 최대 절전 모드가 임베디드 분야를로드 할 수 없습니다, 요약합니다. 원래의 문제에 관해서라면, 나는 @Embeddable이 클래스 계층 구조에서 사용할 때 희박하다는 것을 추측 할 수 있습니다. 그리고 embeddable 클래스의 한 레벨에 모든 embeddable 필드를 유지하는 것이 가장 좋습니다. 그게 문제가되기를 바랍니다. 우리는 그것이 내일 일하기를 계속할 지 지켜 볼 것입니다.