JDBC模塊提供的ORM主要是針對單實體操作,實際業(yè)務(wù)中往往會涉及到多表關(guān)聯(lián)查詢以及返回多個表字段,在單實體ORM中是無法將JDBC結(jié)果集記錄自動轉(zhuǎn)換為實體對象的,這時就需要對結(jié)果集數(shù)據(jù)自定義處理來滿足業(yè)務(wù)需求。
若想實現(xiàn)結(jié)果集數(shù)據(jù)的自定義處理,需要了解以下相關(guān)接口和類:
IResultSetHandler接口:結(jié)果集數(shù)據(jù)處理接口,用于完成將JDBC結(jié)果集原始數(shù)據(jù)的每一行記錄進(jìn)行轉(zhuǎn)換為目標(biāo)對象,JDBC模塊默認(rèn)提供了該接口的三種實現(xiàn):
EntityResultSetHandler:采用實體類存儲結(jié)果集數(shù)據(jù)的接口實現(xiàn),此類已經(jīng)集成在ISession會話接口業(yè)務(wù)邏輯中,僅用于處理單實體的數(shù)據(jù)轉(zhuǎn)換;
MapResultSetHandler:采用Map存儲結(jié)果集數(shù)據(jù)的接口實現(xiàn);
ArrayResultSetHandler:采用Object[]數(shù)組存儲結(jié)果集數(shù)據(jù)的接口實現(xiàn);
ResultSetHelper類:數(shù)據(jù)結(jié)果集輔助處理工具,用于幫助開發(fā)人員便捷的讀取和遍歷結(jié)果集中數(shù)據(jù)內(nèi)容,僅支持由 ArrayResultSetHandler 和 MapResultSetHandler 產(chǎn)生的結(jié)果集數(shù)據(jù)類型;
下面通過簡單的多表關(guān)聯(lián)查詢來介紹IResultSetHandler接口和ResultSetHelper類如何配合使用:
示例代碼一:使用ArrayResultSetHandler或MapResultSetHandler處理結(jié)果集數(shù)據(jù);
IResultSet<Object[]> _results = JDBC.get().openSession(new ISessionExecutor<IResultSet<Object[]>>() { public IResultSet<Object[]> execute(ISession session) throws Exception { // 通過查詢對象創(chuàng)建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")); // 執(zhí)行查詢并指定采用Object[]數(shù)組存儲結(jié)果集數(shù)據(jù),若采用Map存儲請使用:IResultSetHandler.MAP return session.find(SQL.create(_uSelect), IResultSetHandler.ARRAY); } }); // 采用默認(rèn)步長(step=1)逐行遍歷 ResultSetHelper.bind(_results).forEach(new ResultSetHelper.ItemHandler() { public boolean handle(ResultSetHelper.ItemWrapper wrapper, int row) throws Exception { System.out.println("當(dāng)前記錄行數(shù): " + row); // 通過返回的結(jié)果集字段名取值 String _id = wrapper.getAsString("id"); String _uname = wrapper.getAsString("username"); // 也可以通過索引下標(biāo)取值 Double _money = wrapper.getAsDouble(2); // 也可以直接將當(dāng)前行數(shù)據(jù)賦值給實體對象或自定義JavaBean對象 wrapper.toEntity(new User()); // 當(dāng)賦值給自定義的JavaBean對象時需要注意返回的字段名稱與對象成員屬性名稱要一一對應(yīng)并且要符合命名規(guī)范 // 例如:對象成員名稱為"userName",將與名稱為"user_name"的字段對應(yīng) wrapper.toObject(new User()); // 返回值將決定遍歷是否繼續(xù)執(zhí)行 return true; } }); // 采用指定的步長進(jìn)行數(shù)據(jù)遍歷,此處step=2 ResultSetHelper.bind(_results).forEach(2, new ResultSetHelper.ItemHandler() { public boolean handle(ResultSetHelper.ItemWrapper wrapper, int row) throws Exception { // 代碼略...... return true; } });
示例代碼二:使用自定義IResultSetHandler處理結(jié)果集數(shù)據(jù);
// 自定義JavaBean對象,用于封裝多表關(guān)聯(lián)的結(jié)果集的記錄 public class CustomUser { private String id; private String username; private Double money; // 忽略Getter和Setter方法 } // 修改示例一的代碼,將結(jié)果集中的每一條記錄轉(zhuǎn)換成自定義的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")); // 通過實現(xiàn)IResultSetHandler接口實現(xiàn)結(jié)果集的自定義處理 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; } }); } });
更多建議: