0

私は、Oracle の組み込み「HR」データベース スキーマを使用するサンプル Java アプリケーションを開発しています。テーブルの行を Java オブジェクトとして扱いたいと考えています。HR スキーマの表の 1 つである EMPLOYEES は、自己参照型です。EMPLOYEES テーブルの別の行への外部キー (NULL でない場合) を含む MANAGER_ID 列があります。

オブジェクト指向の用語で言えば、問題は、特定の Employee オブジェクトのマネージャー (別の Employee オブジェクト) にアクセスする方法です。指定された Employee オブジェクトのマネージャーもマネージャーを持つことができるため、一括読み込みは良い解決策ではないようです。この状況で熱心にロードするオブジェクトの数は無制限です。

ここまでで決めたことは、Employee オブジェクトをインスタンス化するときに MANAGER_ID フィールドを熱心にロードすることです。次に、Employee のマネージャである Employee オブジェクトが (getManager()メソッドを介して) 要求されると、後者が遅延ロードされます。コード内:

public class Employee
{
    private int id;
    private int managerId;
    private Employee manager;

    public int getId()
    {
        return id;
    }

    public Employee getManager()
    {
        if(manager == null && managerId > 0)
        {
            // Lazy loading!
        }

        return manager;
    }

    public void setManager(Employee manager)
    {
        this.manager = manager;
        this.managerId = manager.getId();
    }
}

それで、これは良いアプローチですか?私が抱えている唯一の問題は、遅延読み込みを実装する方法です。Employee オブジェクトはそのインスタンス化子への参照を必要とするように思われます。おそらく、それはマネージャの Employee オブジェクトをインスタンス化するのと同じことです。

また、独自の ORM フレームワークを展開する代わりに、世の中にある多くの ORM フレームワークの 1 つを使用できることもわかっていますが、基礎となるプロセスについてより多くの洞察を得るために、これを自分で行っています。

編集: 明確にするために、この取り組みのための私のアーキテクチャ (そのようなもの) には、Java EE はまったく含まれていません。これは、クライアントが単純な RMI を介してサーバーとやり取りする Java SE アーキテクチャです。

また、上記の Employee クラスは、遅延読み込みを実行するために DAO への参照を明らかに必要とします。ただし、次の理由により、これが必ずしも密結合であるとは考えていません。

  1. Employee オブジェクトは、DAO が実装する抽象インターフェイスへの参照を保持できます。および/または
  2. Employee オブジェクトはサーバー オブジェクトへの参照を保持でき、サーバー オブジェクトは DAO への (プライベート) 参照を保持します。

#2 の場合、Employee オブジェクトが参照するサーバー オブジェクトは、おそらくクライアントが参照するものと同じであることに注意してください。

4

1 に答える 1

1

他の ORM を知っている場合は、その方法を調べてみませんか? 特に、Hibernate の遅延読み込みプロキシは興味深いものです。

Hibernate は、まだロードされていない従業員オブジェクトへの参照をカプセル化する Employee のサブクラスを (実行時に、バイトコード生成を使用して) 作成します。このクラスで任意のメソッド ( 以外getId()) を呼び出すと、参照先の従業員オブジェクトが読み込まれ、それに委譲されます。

あなたのアプローチと比較すると、これには、関連付けごとに遅延読み込みのサポートをコーディングする必要がなく、すべての関連付けに対して一度コーディングできるという利点があり、データベース アクセス コードでドメイン モデル (ビジネス ロジックをホストする) を汚染することを回避できます。また、呼び出し元は、オブジェクトの状態にアクセスしない限り、オブジェクトをロードせずに操作できます。たとえば、次のことができます。

void switchJobs(Employee e1, Employee e2) {
    Employee m1 = e1.getManager();  // doesn't load the manager!
    e1.setManager(e2.getManager()); // doesn't load the manager!
    e2.setManager(m1);
}

また、Hibernate はトランザクションで同じマネージャーを複数回ロードすることはありませんが、既にロードされている永続オブジェクトまたは遅延ロード プロキシを再利用します。これにより、オブジェクト モデルのパフォーマンスと一貫性の両方が向上します。つまり、複数の従業員がマネージャーを共有し、1 人の従業員がそれを変更した場合、他の従業員はその変更を認識し、マネージャーは == を使用して比較できます。

于 2010-12-17T01:46:41.130 に答える