web-dev-qa-db-ja.com

複合主キー、外部キー。オブジェクトまたはキーへの参照?

FooBarの2つのクラスがあります。データベース内のテーブルは次のようになります。

_|Foo|
|id : INT (PK) | bar_id : INT (PK, FK) |

|Bar|
|id : INT (PK) |
_

通常、私はそれを次のようにマップします:

_@Entity
public class Bar
{
    @Id
    @Column(name = "id")
    private int id;

    @OneToMany
    private Set<Foo> foo;
}

@Entity
public class Foo
{
    @EmbeddedId
    private FooPK key;

    @MapsId("barId")
    @ManyToOne
    @JoinColumn(name = "bar_id", referencedColumnName = "id")
    private Bar bar;
}

@Embeddable
public class FooPK
{
    @Column(name = "id")
    private int id;
    @Column(name = "bar_id")
    private int barId;
}
_

ただし、FooPKのIDは大まかにマッピングされているため、手動で接続する必要があります。緩いIDの代わりにオブジェクトを使用してマップするソリューションをお勧めします。私は次のことを試しましたが、(もちろん)うまくいきませんでしたが、私が何を達成したいのかがわかると思います:

_@Entity
public class Bar
{
    @Id
    @Column(name = "id")
    private int id;

    @OneToMany
    private Set<Foo> foo;
}

@Entity
public class Foo
{
    @EmbeddedId
    private FooPK key;

    @MapsId("barId")
    @ManyToOne
    @JoinColumn(name = "bar_id", referencedColumnName = "id")
    @Access(AccessType.FIELD)
    private Bar getBar()
    {
        return key.getBar();
    }
}

@Embeddable
public class FooPK
{
    @Column(name = "id")
    private int id;

    @Transient
    private Bar bar;

    //....

    @Column(name = "bar_id")
    @Access(AccessType.PROPERTY)
    private int getBarId
    {
        return bar.getId();
    }
}
_

後者のソリューションのもう1つの問題は、FooPKgetBarId()メソッドにsetBarId(Int)メソッドが必要なことです。 IDを使用したオブジェクトの設定は、データアクセス層にアクセスすることで実行できますが、これは(私の意見では)ビジネス/ドメイン/データ層の分離に違反します。

じゃあ何をすればいいの?最初の解決策を使用して、IDを手動で同期しますか、それとも別の(ベスト)プラクティスがありますか?

14
siebz0r

JPA 2:複合主キークラス の説明を参照して、FooクラスとFooPKクラスに次の変更を加えます。

@Entity
public class Foo {

    @EmbeddedId
    private FooPK key;

    @MapsId("barId") //references EmbeddedId's property
    @JoinColumn(name = "bar_id", referencedColumnName = "id")
    @ManyToOne
    private Bar bar;
}

@Embeddable
public class FooPK {

    @Column(name = "id")
    private int id;
    @Column(name = "bar_id")
    private int barId;
}

最初にFIELDアクセスで機能させてから、PROPERTYアクセスを適用することをお勧めします。

じゃあ何をすればいいの?最初の解決策を使用して、IDを手動で同期しますか、それとも別の(ベスト)プラクティスがありますか?

苦痛から身を守る-IDを自動的に生成します。

23
JMelnik