10

Hibernateエンティティ階層には次の種類のクラスがあります。私は2つの具体的なサブクラスとを作成しようとしていSub1ClassますSub2Classfieldこれらは、で定義されている識別子列()で区切られていますMappedSuperClassEntitySuperClass他のエンティティによって参照される抽象エンティティクラスがあります。Sub1Class他のエンティティは、実際に参照しているか、またはを参照しているかどうかを気にする必要はありませんSub2Class

これは実際に可能ですか?現在、このエラーが発生します(列定義は、Sub1ClassとEntitySuperClassで2回継承されるため):

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

に追加@MappedSuperClassするとEntitySuperClass、hiberanteからアサーションエラーが発生します。クラスがエンティティであり、マップされたスーパークラスであるかどうかはわかりません。@Entityから削除するEntitySuperClassと、クラスはエンティティではなくなり、他のエンティティから参照できなくなります。

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;
    }

}
4

4 に答える 4

16

私のプロジェクトでは、次のように実行されます。

@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
}

そしてそれは動作します。あなたの問題は、スーパークラスの定義で弁別子フィールドを不必要に定義していることだと思います。それを削除すると、動作します。

于 2010-07-14T10:26:49.893 に答える
13

識別子列を通常のプロパティとして使用するには、このプロパティを。で読み取り専用にする必要があります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 { 
    ...
}
于 2010-07-14T11:10:59.087 に答える
2

データベース列は、読み取り/書き込みフィールド(insertable=trueおよび/またはを含むフィールド)として1回だけマップでき、読み取り専用フィールド(およびupdatable=true)として何度でもマップできます。列を読み取り/書き込みマッピングとしてカウントするため、追加の読み取り/書き込みマッピングを作成することはできません。insertable=false updatable=false@DiscriminatorColumn

@DiscriminatorColumnHibernateは、具象クラスインスタンスに基づいてバックグラウンドで指定された値を設定します。そのフィールドを変更できる場合は、@DiscriminatorColumnフィールドのサブクラスと値が一致しないようにフィールドを変更できます。

于 2010-07-15T06:12:42.523 に答える
0

基本的なことの1つ:DBからディスクリミネーター列を取得する必要は事実上ありません。その情報は、@DiscriminatorValueタグで使用するコード内にすでに存在している必要があります。DBからそれを読む必要がある場合は、ディスクリミネーターを割り当てる方法を慎重に再検討してください。

最終的なエンティティオブジェクトで必要な場合は、識別子の値から列挙型を実装し、それを@Transientフィールドに返すことをお勧めします。

@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; }
}
于 2013-11-22T20:06:04.777 に答える