進階特性—多表查詢及自訂結果集資料處理


多表查詢及自訂結果集資料處理

JDBC模組提供的ORM主要是針對單一實體操作,實際業務中往往會涉及多表關聯查詢以及傳回多個表字段,在單一實體ORM中是無法將JDBC結果集記錄自動轉換為實體物件的,這時就需要對結果集資料自訂處理來滿足業務需求。

若想實現結果集資料的自訂處理,需要了解以下相關接口和類別:

  • IResultSetHandler接口:結果集資料處理接口,用於完成將JDBC結果集原始資料的每一行記錄進行轉換為目標對象,JDBC模組預設提供了此介面的三種實作:

    EntityResultSetHandler:採用實體類別儲存結果集資料的介面實現,此類別已經整合在ISession會話介面業務邏輯中,僅用於處理單一實體的資料轉換;

    MapResultSetHandler:採用Map儲存結果集資料的介面實作;

    ArrayResultSetHandler:採用Object[ ]陣列儲存結果集資料的介面實作;

  • ResultSetHelper類別:資料結果集輔助處理工具,用於協助開發人員便捷的讀取和遍歷結果集中資料內容,僅支援由ArrayResultSetHandler 和MapResultSetHandler 產生的結果集資料類型;

下面透過簡單的多表關聯查詢來介紹IResultSetHandler介面和ResultSetHelper類別如何配合使用:

# #範例程式碼一:使用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;
        }
    });
##範例程式碼二:使用自訂IResultSetHandler處理結果集資料;

#範例程式碼二:使用自訂IResultSetHandler處理結果集資料;
    // 自定义JavaBean对象,用于封装多表关联的结果集的记录
    public class CustomUser {

        private String id;

        private String username;

        private Double money;

        // 忽略Getter和Setter方法
    }

    // 修改示例一的代码,将结果集中的每一条记录转换成自定义的CustomUser对象
    IResultSet<CustomUser> _results = JDBC.get().openSession(new ISessionExecutor<IResultSet<CustomUser>>() {
        public IResultSet<CustomUser> execute(ISession session) throws Exception {
            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"));

            // 通过实现IResultSetHandler接口实现结果集的自定义处理
            return session.find(SQL.create(_uSelect), new IResultSetHandler<CustomUser>() {
                public List<CustomUser> handle(ResultSet resultSet) throws Exception {
                    List<CustomUser> _results = new ArrayList<CustomUser>();
                    while (resultSet.next()) {
                        CustomUser _cUser = new CustomUser();
                        _cUser.setId(resultSet.getString("id"));
                        _cUser.setUsername(resultSet.getString("username"));
                        _cUser.setMoney(resultSet.getDouble("money"));
                        //
                        _results.add(_cUser);
                    }
                    return _results;
                }
            });
        }
    });

####