2010-07-14 1 views
9

다음과 같은 종류의 최대 절전 모드 엔터티 계층 클래스가 있습니다. 나는 두 개의 구체적인 서브 클래스 인 Sub1ClassSub2Class을 가지고있다. 이들은 MappedSuperClass에 정의 된 판별 자 열 (field)으로 구분됩니다. 다른 엔터티가 참조하는 추상 엔터티 클래스 EntitySuperClass이 있습니다. 다른 엔터티는 실제로 Sub1Class 또는 Sub2Class을 참조하는지는 신경 쓰지 않아야합니다.Hibernate, 단일 테이블 상속 및 식별자 클래스로 슈퍼 클래스의 필드 사용

실제로 가능한가요? (열 정의가 EntitySuperClass Sub1Class과 두 번 상속되기 때문에) 현재이 오류를 얻을 :

Repeated column in mapping for entity: my.package.Sub1Class column: field (should be mapped with insert="false" update="false") 

내가 hiberante에서 @MappedSuperClassEntitySuperClass에, 그럼 내가 얻을 주장의 오류를 추가하는 경우 : 클래스가 모두있는 경우는 좋아하지 않는다 엔티티와 매핑 된 수퍼 클래스. 내가 EntitySuperClass에서 @Entity을 제거하면 클래스가 더 이상 실체없는 다른 개체에서 참조 할 수 없습니다

MappedSuperClass 외부 패키지의 일부이기 때문에 가능한 경우는 변경 될 수 없습니다.

내 클래스 :

가 이런 식으로 이루어집니다 내 프로젝트에서
@MappedSuperclass 
public class MappedSuperClass { 
    private static final String ID_SEQ = "dummy_id_seq"; 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = ID_SEQ) 
    @GenericGenerator(name=ID_SEQ, strategy="sequence") 

    @Column(name = "id", unique = true, nullable = false, insertable = true, updatable = false) 
    private Integer id; 

    @Column(name="field", nullable=false, length=8) 
    private String field; 

    public Integer getId() { 
     return id; 
    } 
    public void setId(Integer id) { 
     this.id = id; 
    } 
    public String getField() { 
     return field; 
    } 
    public void setField(String field) { 
     this.field = field; 
    } 
} 


@Entity 
@Table(name = "ACTOR") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="field", discriminatorType=DiscriminatorType.STRING) 
abstract public class EntitySuperClass extends MappedSuperClass { 


    @Column(name="description", nullable=false, length=8) 
    private String description; 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 
} 

@Entity 
@DiscriminatorValue("sub1") 
public class Sub1Class extends EntitySuperClass { 

} 


@Entity 
@DiscriminatorValue("sub2") 
public class Sub2Class extends EntitySuperClass { 

} 


@Entity 
public class ReferencingEntity { 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    private Integer id; 

    @Column 
    private Integer value; 

    @ManyToOne 
    private EntitySuperClass entitySuperClass; 


    public Integer getId() { 
     return id; 
    } 

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

    public Integer getValue() { 
     return value; 
    } 

    public void setValue(Integer value) { 
     this.value = value; 
    } 

    public EntitySuperClass getEntitySuperClass() { 
     return entitySuperClass; 
    } 

    public void setEntitySuperClass(EntitySuperClass entitySuperClass) { 
     this.entitySuperClass = entitySuperClass; 
    } 

} 
+0

:

당신이 최종 엔티티 객체에 필요한 경우, 하나의 좋은 방법은 판별 값에서 열거를 구현하고 @Transient 필드에 저장 위치를 ​​반환 할 수 있습니다 기둥? 이 열은 일반적으로 노출하지 않으려는 "숨겨진"구현 세부 정보입니다. –

+0

discriminator 열은 이미 외부 패키지의 일부인 MappedSuperClass에 노출되어 있습니다. 가능한 경우 수정하지 않으려는 패키지. –

답변

14

:

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name = "field", discriminatorType = DiscriminatorType.STRING) 
@DiscriminatorValue("dummy") 
public class EntitySuperClass { 
    // here definitions go 
    // but don't define discriminator column here 
} 

@Entity 
@DiscriminatorValue(value="sub1") 
public class Sub1Class extends EntitySuperClass { 
    // here definitions go 
} 

을 그리고 그것은 작동합니다. 문제는 슈퍼 클래스 정의에서 discriminator 필드를 불필요하게 정의하는 것입니다. 그것을 제거하면 효과가 있습니다.

12

discriminator 열을 일반 속성으로 사용하려면이 속성을 읽기 전용으로 insertable = false, updatable = false으로 설정해야합니다. 당신이 MappedSuperClass을 변경할 수 없기 때문에, 당신은 @AttributeOverride를 사용해야합니다 :

@Entity 
@Table(name = "ACTOR") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="field", discriminatorType=DiscriminatorType.STRING) 

@AttributeOverride(name = "field", 
    column = @Column(name="field", nullable=false, length=8, 
     insertable = false, updatable = false)) 

abstract public class EntitySuperClass extends MappedSuperClass { 
    ... 
} 
2

당신은 읽기 - 쓰기 필드 (insertable=true 및/또는 updatable=true이있는 필드) 및 횟수 등으로 한 번만 데이터베이스 열을 매핑 할 수 있습니다 읽기 전용 필드 (insertable=falseupdatable=false). @DiscriminatorColumn 열을 사용하면 읽기 - 쓰기 매핑으로 계산되므로 추가 읽기 - 쓰기 매핑을 가질 수 없습니다.

Hibernate는 구체적인 클래스 인스턴스를 기반으로 장면 뒤에서 @DiscriminatorColumn으로 지정된 값을 설정합니다. 해당 필드를 변경할 수 있다면 필드의 하위 클래스와 값이 일치하지 않도록 @DiscriminatorColumn 필드를 수정할 수 있습니다.

0

하나의 기본 요소 : DB에서 discriminator 열을 검색 할 필요가 없습니다. @DiscriminatorValue 태그에서 사용하는 코드 내에 이미 해당 정보가 있어야합니다. DB에서 읽어야 할 필요가 있다면, discriminators를 할당하는 방법을 신중히 고려하십시오. 그런데 왜 당신이 판별을 보여주고 싶지 않는

@Entity 
@Table(name="tablename") 
@DiscriminatorValue(Discriminators.SubOne.getDisc()) 
public class SubClassOneEntity extends SuperClassEntity { 

    ... 

    @Transient 
    private Discriminators discriminator; 

    // Setter and Getter 
    ... 
} 

public enum Discriminators { 
    SubOne ("Sub1"), 
    SubOne ("Sub2"); 

    private String disc; 
    private Discriminators(String disc) { this.disc = disc; } 
    public String getDisc() { return this.disc; } 
}