高级特性—多表查询及自定义结果集数据处理


多表查询及自定义结果集数据处理

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处理结果集数据;

    // 自定义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;
                }
            });
        }
    });