高度な機能 - マルチテーブル クエリとカスタム結果セット データ処理


複数テーブルのクエリとカスタム結果セットのデータ処理

JDBC モジュールが提供する ORM は、主に単一エンティティの操作に使用され、単一エンティティの ORM では、複数のテーブルに関連するクエリと複数のテーブル フィールドを返すことがよくあります。 JDBC 結果セット レコードをエンティティ オブジェクトに自動的に変換できないため、この場合、ビジネス ニーズを満たすために結果セット データのカスタム処理が必要になります。

結果セット データのカスタマイズされた処理を実装したい場合は、次の関連インターフェイスとクラスを理解する必要があります:

  • IResultSetHandler インターフェイス: 結果セット データ処理インターフェイス。JDBC 結果セットの各行の変換を完了するために使用されます。元のデータをターゲット オブジェクトに格納する場合、JDBC モジュールはデフォルトでこのインターフェイスの 3 つの実装を提供します:

    EntityResultSetHandler: エンティティ クラスを使用して結果セット データを格納するインターフェイス実装。このクラスは ISession セッション インターフェイスのビジネス ロジックに統合されており、単一エンティティの処理にのみ使用されます。

    MapResultSetHandler: 結果セット データを保存するために Map を使用するインターフェイス実装。

  • ResultSetHelper クラス: データ結果セットの補助処理ツール。開発者が結果セット内のデータ コンテンツを簡単に読み取ったり走査したりできるようにするため、ArrayResultSetHandler と MapResultSetHandler によって生成された結果セット データ型のみがサポートされます。
  • 以下に紹介します。単純な複数テーブル関連付けクエリを通じて IResultSetHandler インターフェイスと ResultSetHelper クラスを併用する方法:

サンプル コード 1: ArrayResultSetHandler または MapResultSetHandler を使用して結果セット データを処理します。

    IResultSet<Object[]> _results = JDBC.get().openSession(new ISessionExecutor<IResultSet<Object[]>>() {
        public IResultSet<Object[]> execute(ISession session) throws Exception {
            // 通过查询对象创建SQL语句:
            //
            // SELECT u.id id, u.username username, ue.money money 
            //          FROM user u LEFT JOIN user_ext ue ON u.id = ue.uid
            //
            Select _uSelect = Select.create(User.class, "u")
                    .join(Join.left(UserExt.TABLE_NAME).alias("ue")
                            .on(Cond.create()
                                    .opt("u", User.FIELDS.ID, Cond.OPT.EQ, "ue", UserExt.FIELDS.UID)))
                    .field(Fields.create()
                            .add("u", User.FIELDS.ID, "id")
                            .add("u", User.FIELDS.USER_NAME, "username")
                            .add("ue", UserExt.FIELDS.MONEY, "money"));

            // 执行查询并指定采用Object[]数组存储结果集数据,若采用Map存储请使用:IResultSetHandler.MAP
            return session.find(SQL.create(_uSelect), IResultSetHandler.ARRAY);
        }
    });

    // 采用默认步长(step=1)逐行遍历
    ResultSetHelper.bind(_results).forEach(new ResultSetHelper.ItemHandler() {
        public boolean handle(ResultSetHelper.ItemWrapper wrapper, int row) throws Exception {
            System.out.println("当前记录行数: " + row);

            // 通过返回的结果集字段名取值
            String _id = wrapper.getAsString("id");
            String _uname = wrapper.getAsString("username");

            // 也可以通过索引下标取值
            Double _money = wrapper.getAsDouble(2);

            // 也可以直接将当前行数据赋值给实体对象或自定义JavaBean对象
            wrapper.toEntity(new User());

            // 当赋值给自定义的JavaBean对象时需要注意返回的字段名称与对象成员属性名称要一一对应并且要符合命名规范
            // 例如:对象成员名称为"userName",将与名称为"user_name"的字段对应
            wrapper.toObject(new User());

            // 返回值将决定遍历是否继续执行
            return true;
        }
    });

    // 采用指定的步长进行数据遍历,此处step=2
    ResultSetHelper.bind(_results).forEach(2, new ResultSetHelper.ItemHandler() {
        public boolean handle(ResultSetHelper.ItemWrapper wrapper, int row) throws Exception {
            // 代码略......
            return true;
        }
    });
サンプル コード 2: カスタム IResultSetHandler を使用して結果セットのデータを処理します。