2009-06-11 9 views
10

이것은 Hibnerate 다형성 질문 및 데이터 모델 디자인 질문입니다. 그들은 뒤죽박죽이다. 나는 과거에 최대 절전 모드를 사용했는데, 을 즐겼다. 그러나 가끔 사소한 디자인에 대해서 을 생각하는 것이 어렵다고 생각한다. 최대 절전 모드가 아닙니다. 단지 ORM이 일반적으로 어려울 수 있다는 관찰.최대 절전 모드 다형성

이것은 최대 절전 모드 101 질문이라고 생각하지만 확실하지 않습니다. 내가 성취하려는 것은 심지어 가능하지 않을 수도 있습니다.

나는 사과 과 오렌지색으로 서브 클래스 화 될 추상 클래스의 과일을 가지고있다. 사과와 오렌지에 관한 노트 나 코멘트를 나타내는 노트 클래스가 있습니다. . Apple이나 Orange는 많은 노트를 가질 수 있지만 오직 하나의 Apple 또는 Orange 만 주어진 Note와 연결된 이됩니다.

다음은 클래스의 스케치입니다. 여기서는 지금 객체 ID가 생략 된 부분과 Oleges와 을 구별하는 사과 속성을 생략했습니다. 당분간 나는 내가 사용하는 Hibernate 상속 전략에 대해 강하게 느끼지 않는다. 우리가 사과와 오렌지 모두 필드가 것을 볼 수있어서, 여기에

abstract public class Fruit { 
} 

// Apples have notes written about them: 
public class Apple extends Fruit { 
    private Set<Note> note; 
    ... 

    @OneToMany(cascade = CascadeType.ALL) 
    public Set<Note> getNote() { 
     return note; 
    } 
} 


// Oranges have notes written about them: 
public class Orange extends Fruit { 
    private Set<Note> note; 
    ... 

    @OneToMany(cascade = CascadeType.ALL) 
    public Set<Note> getNote() { 
     return note; 
    } 
} 

는 현재 구현 된 주 클래스입니다. 이 디자인의 결함 또는 부적절한 은 단일 노트 인스턴스가 Apple 또는 Orange 중 하나 인 만을 가리키며 두 가지 모두를 결코 가리 키지 않는다는 것입니다. 따라서 메모가 Apple 에 바인딩 된 경우 Orange 입력란은 불필요하고보기 흉하고 viceversa입니다.

// A note about an Apple or Orange 
public class Note { 
    private String theNote; 
    private Apple apple; 
    private Orange orange; 
    ... 

    // with the usual many to one mapping 
    @ManyToOne 
    @JoinColumn(name = "apple_id") 
    public Apple getApple() { 
     return apple; 
    } 

    // with the usual many to one mapping 
    @ManyToOne 
    @JoinColumn(name = "orange_id") 
    public Orange getOrange() { 
     return orange; 
    } 

    ... 
} 

그러나, 이것은 내가 내 디자인의 기준이 생각 노트 클래스입니다,하지만 난 주석 및 테이블 매핑을 최대 절전 모드에 대하여 으로 이것에 대해 생각하는 방법을 잘 모르겠어요 :

// A note about a fruit: 
public class Note { 
    private String theNote; 
    private Fruit fruit; 
    ... 
} 

그러면 과일은 Apple 또는 Orange 인스턴스 중 하나입니다.

실제로 Apple이나 Orange를 보유 할 Fruit에 대한 참조가 Hibernate ORM 매핑과 조화 될 수 있습니까? 그렇다면 어떻게 누군가가 이야기 할 수 있습니까?

+0

MySQL 데이터베이스를 통해 실행되는 코드로 인해 비슷한 문제가 있습니다. 내 관련 질문으로 나를 도울 용의가 있습니까? 여기에 링크가 있습니다 : http://stackoverflow.com/questions/25252541/generatedvalue-for-a-java-abstract-superclass-over-mysql – CodeMed

답변

13

이것은 절대 가능합니다. 당신은 구현의 각을 반복하는 대신 추상적 인 Fruit 클래스와 노트를 연결할 수 :

@Entity 
@Inheritance 
public abstract class Fruit { 
    private Set<Note> notes; 
    ... 

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "fruit") 
    public Set<Note> getNotes() { 
     return notes; 
    } 
} 

@Entity 
public class Apple extends Fruit { 
    ... 
} 


@Entity 
public class Orange extends Fruit { 
    ... 
} 

@Entity 
public class Note { 
    private String theNote; 

    @ManyToOne 
    private Fruit fruit; 
    ... 
} 

등 봐라!

- 덧글 추가에 기반 : JPA는 상속을 처리하기위한 여러 전략을 제공합니다. relevant section in the Java EE tutorial은 시작하는 데 도움이됩니다.

기본적으로 옵션은 다음과 같습니다

  • 하나 개의 테이블에 모든 것을 저장 및 인 줄 알고 판별 자 컬럼을 사용하여 어떤 유형의
  • 별도의 테이블
  • 각 구상 클래스 (사과와 오렌지를) 저장 과일 테이블

에 외래 키와 공통의 판별 자 컬럼 과일 테이블, 그리고 애플과 오렌지 테이블을 갖는

  • 다른 편집 : 이것은 JPA 질문이 아니라 최대 절전 모드임을 알 수 있습니다. 옵션이 동일하기 때문에 차이를 너무 많이 만들지는 않습니다. 다음은 relevant section in the Hibernate docs입니다.

  • +0

    임시 -1 :이 질문에 대답하지 않습니까? 당신은 과일과 노트 사이의 관계에 대해 최대 절전 모드라고 말했다. 과일을 애플이나 오렌지 중 어느쪽에 모으는 지 어떻게 알 수 있습니까? –

    +1

    @ Jason : 실제로, 그것은 매우 문자 그대로입니다. 질문을 다시 읽으면, 특히 두 번째 코드 블록에서 시작하는 마지막 단락을 읽으면, 제가 제공하는 코드는 정확히 ae6rt가 요구하는 코드입니다. – Henning

    +0

    -1이 제거되었습니다. Apple이 Orange와 다른 방식으로 데이터베이스에 저장하는 방법을 자세히 설명해 주시겠습니까? –

    4

    이 패턴은 Hibernate 기반 데이터 계층에서 매우 일반적입니다. 내부적으로 작동하는 방식은 상속 전략이 사용되는 방식에 따라 크게 달라집니다.

    클래스 당 테이블 또는 하위 클래스 상속 테이블을 사용할 때 모든 하위 클래스/클래스에 대한 테이블이 만들어집니다. 예를 들어, 귀하의 테이블에는 Fruit과 Apple/Orange 사이에 외래 키를 참조하는 두 테이블 AppleOrange이 있습니다. 하나의 과일 (사과 또는 오렌지)을 ID로 요청할 때, Hibernate는 애플 테이블과 오렌지 테이블을 사용하여 Fruit 테이블을 외부에 연결합니다. 각 행은 필드가 검색된 테이블에 따라 Apple 또는 Orange로 변환됩니다.

    또 다른 가능성은 판별자를 사용하는 것입니다. 판별 자 필드 (예 : fruit_type, 값이 appleorange 인 단일 테이블 Fruit)가 사용됩니다. 이 필드의 값에 따라 Hibernate는 해당 객체가 Apple인지 Orange인지를 결정합니다.

    열심히로드하는 경우, Hibernate가 Note 객체를로드 할 때 열심히 해당 Fruit을 가져오고 이에 따라 Apple 또는 Orange 인스턴스로 과일 필드를 채 웁니다.

    lazy fetching의 경우 과일 필드는 Fruit 인터페이스를 구현하는 프록시가됩니다. 실제 과일 필드가로드 될 때까지는 그 유형이 결정되지 않습니다.

    일부 검색어에 대한 답변입니다.