4

JPA/Hibernate を使用して、グループとアカウントの 2 つのエンティティ間の関係をモデル化したいと考えています。アカウントは複数のグループを持つことができますが、その逆はできないため、アカウントとグループの間には OneToMany の関係があります。Account私の同僚は、エンティティなどGroupをモデル化することを提案しました

public class Account {
    private List<Group> groups = new ArrayList<Group>();

    public Account() {}

    public void setGroups(List<Group> usergroups) {
        this.groups = groups;
    }

    @OneToMany(mappedBy = "account")
    public List<Group> getGroups() {
        return groups;
    }
}

public class Group {
    private String name;
    private Account account;

    public Group() {}

    public Group(String name, Account account) {
        this.name = name;
        addToAccount(account);
    }

    public void addToAccount(Account account) {
        setAccount(account);
        List<Group> accountGroups = account.getGroups();
        accountGroups.add(this);
    }

    @ManyToOne
    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }
}

私の質問はaddToAccount、のコンストラクターでのヘルパー メソッドの使用についてですGroup。私の同僚によると、この方法が必要なのは、2 つのエンティティの一貫したメモリ モデルを確保するために、2 つのエンティティ間の双方向の関係を両側から更新する必要があるからです。

addToAccountただし、コンストラクターでメソッドを呼び出すことはお勧めできません。

  1. ListofGroupは遅延フェッチされるため、メソッドを呼び出すには 開いaddToAccountているトランザクションが必要です。したがって、のコンストラクターは Group、開いているトランザクション内でのみ呼び出すことができます。私の意見では、これは非常に厄介な制限です。

  2. コンストラクターの引数として指定されたAccountオブジェクトは、コンストラクターGroupによって変更されます。私の意見では、これはコンストラクターの驚くべき副作用であり、Group 起こるべきではありません。

私の提案は、次のような単純なコンストラクターをより適切に使用することでした

 public Group(String name, Account account) {
            this.name = name;
            this.account = account;
        }

双方向の関係を手動で処理します。しかし、多分私は間違っています。休止状態のエンティティを構築するときに双方向の関係を処理する一般的な方法はありますか?

4

2 に答える 2

0

私の経験では、一般的に行われているのとまったく同じようにしています。私の質問は、なぜあなたがグループから直接アカウントを操作したいのかという構造に関するものです (上記のサンプルよりも多くのことが起こっていると思います)。

また、これが OneToMany か ManyToMany のどちらの状況であるかについても質問します (通常、複数のアカウントが 1 つのグループに属し、複数のグループが 1 つのアカウントに属することができますが、それはすべて特定のアカウンティング スキームのセマンティクスにあります...) とにかく: あなた私は(この正確なケースでは)なぜアカウントを直接操作したいのか(遅延ロードされていない限り)疑問に思っていますが、これはまったく問題ありません。

[構成に応じて適切に永続化されるように、いくつかのカスケード ルールを追加する必要がある場合があります。]

アカウントにマッピングすることで、それをアカウントのリストに効果的に追加したことに注意してください。データベースがそのリストを作成するために次にクエリを実行すると、Account エンティティからの参照を見つけてリストにデータが入力されます。

要するに->

public void Group.setAccounts(Account a)
{
  this.account = a;
}

上記で行っていることと実質的に同等です。データベースは、次のようなものをリストに照会して入力します。

//Pseudo SQL
    SELECT g.id FROM Group g WHERE g.account_id = :account_id

したがって、リストはクエリによって定義されるため、遅延ロード (必要な場合とそうでない場合があります) を除けば、グループに追加する必要はありません。

(難しくしすぎないでください。単純に見えます。長い説明で、JPA で何が起こっているかがわかると思います)

于 2011-07-06T14:58:59.367 に答える