2017-08-22 11 views
1

私は、オフィスを扱うSpring JPA(PostgresSQL & H2)サービスを作成しています。私は、独立したオフィス、または子供(遠隔)のオフィスを持つ親オフィス(企業)を持つことができます。オフィスには住所と従業員のリスト(複数のオフィスに所属することができます)があります。私はデザインに苦労しており、あなたが提供できるあらゆる助けに本当に感謝しています。ネストされたHibernateエンティティ

私のテーブルは現在/ devをテストするためにH2にありますので、テーブルに参照整合性がありません。
これは私のモデルを改善できないかどうか疑問に思っています。この種の再帰/ネストされた関係を行う良い方法はありますか?

UPDATE jfneisからの優れたフィードバックに基づいて、私は今、このアプローチを持っている:

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name = "OfficeType") 
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "officeId") 
public abstract class Office { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "officeId", updatable = false, nullable = false) 
    private long officeId; 

    @Column 
    private String name; 
    @Column 
    private String ein; 
    @Column 
    @Temporal(TemporalType.DATE) 
    private Date startDate; 
    @Column 
    @Temporal(TemporalType.DATE) 
    private Date endDate; 

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "addressId", nullable = false) 
    private Address address; 

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @Fetch(value = FetchMode.SUBSELECT) 
    private List<Employee> employees = new ArrayList<>(); 
} 

と本社:

@Entity(name = "CorporateOffice") 
@DiscriminatorValue("Corporate") 
public class CorporateOffice extends Office { 

    @Column 
    private String url; 
} 

やリモートオフィス:

@Entity(name = "RemoteOffice") 
@DiscriminatorValue("Remote") 
public class RemoteOffice extends Office { 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "corporateOfficeId") 
    private Office corporateOffice; 
} 

もし私がどちらのタイプのものであるかを示す列が「office」テーブルに格納されます。

私はさらに何が起こっているかを見ることができますので、私はいくつかのテストデータを播種しています起動時

@Component 
@Transactional 
public class SeedOffices { 

@Autowired 
private OfficeRepository officeRepository; 

@PostConstruct 
public void seedOffices() { 
    CorporateOffice corporate = new CorporateOffice(); 
    corporate.setName("World Domination Corp"); 
    corporate.setUrl("www.corporationsownstheworld.com"); 
    corporate.setStartDate(new Date()); 
    Address corpAddr = new Address(); 
    corpAddr.setAddressLine1("corp line 1"); 
    corpAddr.setCity("Denver"); 
    corporate.setEin("123456789"); 
    corporate.setAddress(corpAddr); 
    officeRepository.save(corporate); 

    RemoteOffice office1 = new RemoteOffice(); 
    office1.setStartDate(new Date()); 
    Address remote1Addr = new Address(); 
    remote1Addr.setAddressLine1("remote 1 line 1"); 
    remote1Addr.setCity("Cheyanne"); 
    office1.setAddress(remote1Addr); 
    officeRepository.save(office1); 
    office1.setCorporateOffice(corporate); 

    RemoteOffice office2 = new RemoteOffice(); 
    Address remote2Addr = new Address(); 
    remote2Addr.setAddressLine1("remote 2 line 1"); 
    remote2Addr.setCity("Calumet"); 
    office2.setAddress(remote2Addr); 
    officeRepository.save(office2); 
    office2.setCorporateOffice(corporate); 
} 

}

答えて

1

これは一種のない主観的な答え(のデザイン質問です答えSOが答えられるはずです)。

とにかく:私は1つのOfficeクラスが気に入らない。本社オフィス(リモートオフィスを持つことができる)とリモートオフィス(親オフィスを持つことができます)の2つの異なる動作のためのクラスは1つだけです。

両方の点での参照は、ビジネス要件次第ですが、私の提案は、共通の属性を持つ抽象クラスOfficeとCorporateOfficeおよびRemoteOfficeという2つの子クラスを持ち、それぞれが望ましい属性を扱います。

両方を単一テーブル戦略を使用して同じテーブルにマップすることができます。 JPAのサブクラス化の戦略については、this articleをご覧ください。


編集:RemoteOfficeマッピングについてのあなたの第二の質問に答える:

私はあなたのRemoteOfficeマッピングが間違っていると信じています。あなたはcorporateOfficeを@OneToManyとして宣言しましたが、実際には@ManyToOne関係ですね。このフィールドに@ManyToOne + @JoinColumnをテストして問題が解決したかどうかを確認してください。

+0

アドバイスと指示をありがとうございます。私は元の質問を更新しました。あなたが気にしないでください。 – sonoerin

+0

@sonoerinが新しい答えで私の質問を編集しました。試してみてください。 – jfneis

+0

チャットでこのディスカッションを続行しましょう(http://chat.stackoverflow.com/rooms/152567/discussion-between-jfneis-and-sonoerin)。 – jfneis