2017-06-05 15 views
2

私はJPAを初めて使い、次のクラスの設計を試してみることにしました。すべてのクラスは、equalsとhashcodeのオーバーライド、gettersとsetter、および空のコンストラクタを持ちます。このエンティティ階層の良いパーシスタンス設計とは何ですか?

私はすべてのエンティティのための基本クラスを持っている:

public abstract class BaseEntity { 
    protected Point loc; 
    protected List<Property> properties = new ArrayList<>(); 
} 

Pointクラスがちょうど標準のxyホルダー

public class Point { 
    private int x, y; 
} 

あるとプロパティクラスは名前とIDを保持:

public class Property { 
    private int id; 
    private String name; 
} 

BaseEntityから継承するクラスは3つあります。最初はハウスです。家はの単一のファミリーを保持することができます。

public class House extends BaseEntity { 
    private Family family; 
} 

public class Tree extends BaseEntity { 
    private String name; 
} 

ファミリーはすぐに表示されます。

public abstract class LivingEntity extends BaseEntity { 
    public static enum Status { ALIVE, DECEASED } 
    int id; 
    Status status; 
} 

だから、階層グラフは

BaseEntity 
     | 
     /|\ 
    /| \ 
    /| \ 
House Tree LivingEntity 
       | 
      /\ 
     Family Member 

とある

public class Family extends LivingEntity { 
    private House house; 
    private List<Minion> members; 
} 

public class Member extends LivingEntity { 
    private Family family; 
    private String name; 
} 

が含まれています。もう一つはすべての生きているエンティティのスーパークラスですコンポジショングラップhは、継承するものに加えて、

House <---> Family ---> {Member, Member, Member, ...} 
      ^   |  |  | 
       |---------------------------- 

です。


ハウスとツリー(equalsメソッドで)自分の位置によって識別されますので、私はその@Idとして使用することができると思います。私は彼らに特定のidフィールドを与えることができますが、それは冗長です。

これは、xとyのコンポジットIDを持つエンティティもPointにする必要があることを意味します。私は、これが同じポイントをDBに複数回保存するかどうかはわかりません。私は異なるBaseEntitiesのセットを保存しますので、2つが同じPointにある場合、ポイントエントリを複製するか、すべてを1つの場所に参照しますか?

ファミリとメンバーは、家から家に移動できるため、IDで定義されます。ですので、@IdとしてLivingEntityにidを使用しますが、BaseEntitiesの@Idと競合します。ここで

は、私が持っている注釈です:

@MappedSuperclass 
public abstract class BaseEntity { 
    @Id 
    protected Point loc; 

    @OneToMany 
    protected List<Property> effects = new ArrayList<>(); 
} 

@Entity 
@IdClass(value = PointID.class) 
public class Point { 
    @Id 
    private int x, y; 
} 

class PointID { 
    int x, y; 
} 

@Entity 
public class Property { 

    @Id 
    protected int id; 

    protected String name; 
} 

@Entity 
public class House extends BaseEntity { 
    @OneToOne 
    private Family family; 
} 

私が正しく、スマートな方法で注釈を使用している場合、私は知らない2 @MappedSuperclassの紛争を除き
@MappedSuperclass 
public abstract class LivingEntity extends BaseEntity { 
    public static enum Status { ALIVE, DECEASED } 

    @Id 
    int id; 

    @Enumerated(EnumType.STRING) 
    Status status; 
} 

@Entity 
public class Family extends LivingEntity { 
    @OneToOne // bidirectional? specify mappedBy? 
    private House house; 

    @OneToMany 
    private List<Minion> members; 
} 

@Entity 
public class Member extends LivingEntity { 
    @ManyToOne // bidirectional? specify mappedBy? 
    private Family family; 

    private String name; 
} 

。この場合、どのようなデザインが良いでしょうか?

+0

'@OneToOne protected String name;とは何ですか?他のエンティティとの関係です。 Stringは「別のエンティティ」ではありません。メインのJPAプロバイダのすべてのドキュメントはこれを説明しています –

+0

@NeilStocktonペーストの間違いをコピーしてください。一定。 – Mark

+0

もう少し細分化する必要があります。 Pointで言及しているように、これがエンティティであるか、独自のアイデンティティーであるか、または所有クラス(埋め込み可能)のデータのカプセル化であるかを最初に把握する必要があります。あなたのビジネスルールは最も重要です。私は、ツリーとファミリーと 'メンバー'が同じ基本クラスを持つ理由を理解できません。人々は根ざしていないので、住所に関連付けられるかもしれませんが、住所によって定義されません。 – Chris

答えて

0

あなたのビジネス上の理由はわかりません(個々のメンバーだけではなく、家族全体に「生きている」または「死んだ」ステータスがあるのは奇妙に思われます)が、例の場合、

プロパティは主にプロパティ上の資産のコレクションになります。プロパティは、多くのツリーを持つ可能性のある庭がある家です。ポイントを参照するかどうかわからない、または各ツリー/ハウスに独自のポイントがある - それは必要に応じて決まります。または、Propertyを削除して、LivingEntityがBaseFixedObjectsを直接参照できるようにすることもできます。

リレーションシップは双方向である可能性があります。そのため、プロパティはリビングエンティティが結びついているLivingEntityを参照することがあります。リビングエンティティは単一の 'メンバー'またはファミリです。私はこのモデルで共同所有権が家族の外で必要とされるかどうか分かりません。 もしそうなら、複数の所有者を許可してManyToMany関係にする必要があるかもしれません。

このようにして、あなたの家族(おそらく)には定点を持つ家があります。関連付けられたプロパティを介してアクセスできるため、ポイント自体を参照する必要はありません。

関連する問題