2008-09-01 2 views
5
@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
public class Problem { 
    @ManyToOne 
    private Person person; 
} 

@Entity 
@DiscriminatorValue("UP") 
public class UglyProblem extends Problem {} 

@Entity 
public class Person { 
    @OneToMany(mappedBy="person") 
    private List<UglyProblem> problems; 
} 

내가 뭘 하려는지 분명히 생각합니다. @ManyToOne 사람이 UglyProblem 클래스에 상속 될 것으로 기대합니다. 그러나 다음과 같은 예외가있을 것입니다. "UglyProblem 클래스 (mappedBy ="person ")에 해당 속성이 없습니다."@OneToMany가 최대 절전 모드에서 상속과 함께 작동하지 않는 이유

나는 모두 this입니다. Emmanuel Bernard가이 배경에 대한 이유를 설명하는 게시물을 찾을 수 없었습니다.


불행하게도, 최대 절전 모드 설명서에 따라 "@MappedSuperclass 무시로 슈퍼 클래스에서 속성 매핑되지 않습니다."

public class A { 
    private int foo; 
} 

@Entity 
public class B extens A { 
} 

다음 foo은 의미가 클래스 B에 대한 매핑되지 않습니다 필드 :

이 잘 나는 이것이 내가이 두 클래스가 있다면 것을 의미한다 생각합니다. 나는 이런 식으로 뭔가가있는 경우 그러나 :

@Entity 
public class Problem { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

private String name; 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 
} 

@Entity 
public class UglyProblem extends Problem { 

private int levelOfUgliness; 

public int getLevelOfUgliness() { 
    return levelOfUgliness; 
} 

public void setLevelOfUgliness(int levelOfUgliness) { 
    this.levelOfUgliness = levelOfUgliness; 
} 
} 

을 나는 클래스 UglyProblem이 fileds idname과 같은 테이블을 사용하여 매핑 할 두 클래스를 기대합니다. (실제로 이것은 정확하게 발생합니다. 나는 방금 다시 확인했습니다.)

CREATE TABLE "problem" (
    "DTYPE" varchar(31) NOT NULL, 
    "id" bigint(20) NOT NULL auto_increment, 
    "name" varchar(255) default NULL, 
    "levelOfUgliness" int(11) default NULL, 
    PRIMARY KEY ("id") 
) AUTO_INCREMENT=2; 

내 질문으로 돌아 간다 :

내가 @ManyToOne 사람이 UglyProblem 클래스에 의해 상속 될 것으로 예상 나는이 표를 가지고있다.

다른 모든 매핑 된 필드가 상속되므로 ManyToOne 관계에 대해이 예외를 적용 할 이유가 없습니다.


그래, 나는 그것을 보았다. 사실, 필자는 필자의 경우 읽기 전용 솔루션을 사용했다. 그러나 나의 질문은 "왜 ..."이었습니다. 나는 최대 절전 모드 팀의 멤버가 제공 한 설명이 있다는 것을 알고있다. 나는 그것을 발견 할 수 없었고 그래서 내가 왜 물었습니다.

이 디자인 결정의 동기를 찾고 싶습니다.

(내가이 문제에 직면 한 방법에 관심이 있다면 : 나는 최대 절전 모드 3을 사용하여 빌드 된 프로젝트를 상속 받았다. 그것은 Jboss 4.0.something + hibernate가 이미 존재했다는 것이다. 제이 보스 4.2.2에 나는

+0

당신 9 월 4 일에 당신의 편집에 대한 자세한 내용을 추가해야합니다.List를 @OneToMany (mappedBy = "person") 매핑 대신 List 으로 지정하면 문제의 성격이 바뀝니다. 이전에 Person을 문제 목록에 매핑하려고한다고 생각했기 때문에 (Ugl –

답변

4

나는 그것이 Hibernate 팀에 의해 만들어진 현명한 결정이라고 생각한다. 그들은 덜 오만하고 왜 이런 식으로 구현되었는지 분명히 할 수 있습니다.하지만 그것은 Emmanuel, Chris, Gavin이 어떻게 작동하는지에 대한 것입니다. :)

문제를 이해하려고합시다. 당신의 개념이 "거짓말"이라고 생각합니다. 많이 말하면 문제사람과 관련이 있습니다. 하지만 그 중 하나라고 말하면 사람은 많은 UglyProblem (다른 문제)와 관련이 없습니다. 그 디자인에 문제가 있습니다.

데이터베이스에 매핑되는 방법을 상상해보십시오. 당신은 너무, 단일 테이블 상속이 있습니다

  _____________ 
      |__PROBLEMS__|   |__PEOPLE__| 
      |id <PK>  |   |   | 
      |person <FK> | -------->|   | 
      |problemType |   |_________ | 
      -------------- 

어떻게 최대 절전 모드는 problemType 동일 UP 경우 문제사람들 관련 확인하기 위해 데이터베이스를 시행 할 것입니다? 그것은 해결하기가 매우 어려운 문제입니다. 그래서 이런 종류의 관계가 필요하다면, 모든 서브 클래스는 자신의 테이블에 있어야합니다. 그게 뭐야 @MappedSuperclass 않습니다.

PS : 추악한 도면 죄송합니다 : D

1

난 당신이 문제 슈퍼 클래스에 주석을 달 필요가 있다고 생각) ...이 "@OneToMany mappedBy"의 매핑을 상속하고 기존 설정에서 잘 작동되는 것을 발견 @MappedSuperclass대신 @Entity 대신.

4

안타깝게도, 최대 절전 모드 documentation에 따르면 "@MappedSuperclass로 매핑되지 않은 수퍼 클래스의 속성은 무시됩니다." 나는 이것에 대해서도 달려 들었다. 내 솔루션은 엔티티 bean 자체보다는 인터페이스를 통해 원하는 상속을 표현하는 것이 었습니다.당신이 코드를 사용하는 경우 추가 혜택으로

@MappedSuperclass 
public abstract class AbstractProblemImpl implements Problem { 
    @ManyToOne 
    private Person person; 

    public Person getPerson() { 
     return person; 
    } 
} 

@Entity 
public class ProblemImpl extends AbstractProblemImpl implements Problem { 
} 

@Entity 
public class UglyProblemImpl extends AbstractProblemImpl implements UglyProblem { 
} 

, 그런 다음

public interface Problem { 
    public Person getPerson(); 
} 

public interface UglyProblem extends Problem { 
} 

추상 슈퍼 클래스와 두 개의 엔티티 서브 클래스를 사용하여이 인터페이스를 구현 : 귀하의 경우에는

는 다음을 정의 할 수 있습니다 이러한 인터페이스를 구현하는 실제 엔티티 bean이 아닌 인터페이스를 사용하면 나중에 기본 매핑을 쉽게 변경할 수 있습니다 (호환성을 손상시킬 위험이 적음).

0

은 내가 OneToMany mappedBy 문제를 수행하는 방법을 알아 냈어.

원래 게시물의 UglyProblem 파생 클래스입니다. 콜백 메소드는 부모 클래스가 아닌 파생 클래스에 있어야합니다.

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@ForceDiscriminator 
public class Problem { 

} 

@Entity 
@DiscriminatorValue("UP") 
public class UglyProblem extends Problem { 
    @ManyToOne 
    private Person person; 
} 

@Entity 
public class Person { 
    @OneToMany(mappedBy="person") 
    private List<UglyProblem> problems; 
} 

적어도 Hibernate를 사용하기위한 비밀 소스를 찾았습니다. http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html @ForceDiscriminator는 @OneToMany를 판별 자로 사용합니다.

최대 절전 모드 주석이 필요합니다.

5

내 경우에는 SINGLE_TABLE 상속 유형을 사용하려고 했으므로 @MappedSuperclass를 사용하는 것이 옵션이 아니 었습니다.

작동 무엇 매우 깨끗하지 않지만, 쿼리 유형을 강제로 @OneToMany 협회에 최대 절전 모드 전용 @Where 절을 추가하는 것입니다

@OneToMany(mappedBy="person") 
@Where(clause="DTYPE='UP'") 
private List<UglyProblem> problems; 
+0

대신' @ eclipseLink 또는 JPA 일반적으로 많이 받아 들일 것입니다. – Odys

+0

안녕하세요, Odys, EclipseLink에서는 아무 것도 지정하지 않아도됩니다. Hibernate는 일반적으로 oneToMany 주석에서 targetEntity = Person.class를 지정하도록합니다. 필드 1을 가진 엔티티 UglyPerson uglyPerson 필드 2 BeutifulPerfoson beutifulPerson; eclipselink에서, 그는 BeuftifulPerson @DescriminatorValue ("PRETTY_PERSON")를보고 자동으로 알게되고, Hibernate는 이것을 모르고 @ WHERE 절. Eclipselink는 클래스 하이라이팅을 분석하고 eToMany 매핑. – 99Sono

+0

Ecliipselink에서는 클래스 hierarhcy의 일부인 엔티티에 각각 고유 한 요소가 있는지 확인하십시오. @DiscriminatorColumn (이름 = "ENTITY_CLASS", descriminatorType = 문자열) 과 쉽게 최대 절전 모드로 을 @Inheritance (SINGLE_TABLE)를 사용할 수 있습니다 : 같은 엔터티 뭔가 경우 @DiscriminatorValue ("BEAUTIFUL_PERON") descriminator 및 기본 클래스에 추가 WHERE 절을 지정해야하며 계층 구조의 각 하위 요소에 대한 술어를 ENTITY_CLASS로 계속 유지해야하기 때.에이 작업에 상당히 어려움이 있습니다. 그래서 여기에 eclipselink가 앞섰습니다. – 99Sono

관련 문제