带着这个疑问我看了hibernate reference,看到hibernate提供session.createSQLQuery接口,似乎可以满足我的要求,好!让我来试试看,于是有了下面的代码:
public ListgetPublicIndex(String startDate, String endDate) throws SQLException { StringBuffer sql = new StringBuffer(); sql.append("select a.id as id, a.money as deposit, b.money as loan, c.money as loanleave, a.tdate as tdate") .append(" FROM publicindex a inner join publicindex b") .append(" on a.tdate = b.tdate and a.flag = '1' and b.flag = '2'") .append(" inner join publicindex c") .append(" on a.tdate = c.tdate and c.flag = '3'") .append(" where (a.tflag = 2 or a.tflag = 3 or a.tflag = 7) and") .append(" (b.tflag = 2 or b.tflag = 3 or b.tflag = 7) and") .append(" (c.tflag = 2 or c.tflag = 3 or c.tflag = 7) and") .append(" a.tdate >= to_date(?, 'yyyy-mm-dd') and") .append(" a.tdate <= to_date(?, 'yyyy-mm-dd')") .append(" order by a.tdate"); Session session = dao.openSession(); return session.createSQLQuery(sql.toString()).addEntity(Private.class).setParameter(0, startDate).setParameter(1, endDate).list(); }
说明下:dao是公司前辈封装的一个简单框架,同时支持jdbc和hibernate,对于Private.class,仅仅是个bean,并没有写hibernate mapping,测试发现抛了下面的异常:
org.hibernate.MappingException: Unknown entity: com.cuishen.edwview.pojo.Private
于是我就mapping了一个简单的Entity,做了个简单的单表sql查询,如下:
public ListgetTechnicApp(String date) throws SQLException { String sql = "select * from technicappindex t where t.tdate = to_date(?, 'yyyy-mm-dd')"; Session session = dao.openSession(); return session.createSQLQuery(sql).addEntity(TechnicApp.class).setParameter(0, date).list(); }
说明下:将technicappindex表mapping为TechnicApp,测试通过了!看来hibernate的sql query还是不能完全脱离mapping
于是我修改了dao的代码,在jdbc返回结果集做封装的模块中加入了如下代码:
/** * 反射POJO的setter方法,将记录中匹配的列值注入POJO,最后以List返回, * 在不区分大小写的情况下记录中的列名(加上'set'前缀)必须和POJO中的公有setter方法名一致, * 否则将不会被注入 * @param list 要返回的list * @param pojoClassName String 要注入的POJO的包路径, e.g 'com.cuishen.pojo.Cat' * @param rs ResultSet 待封装的原始结果集 */ private static void setPOJO(List list, String pojoClassName, ResultSet rs) { try { ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); // 查询的列数 Method [] methodsToInvoke = new Method[columnCount]; Class pojo = Class.forName(pojoClassName); Method [] methods = pojo.getMethods(); for(int i = 0; i < columnCount; i++) { for(int j = 0; j < methods.length; j++) { String methodName = methods[j].getName(); if(methodName.equalsIgnoreCase("set" + metaData.getColumnName(i + 1))) { methodsToInvoke[i] = methods[j]; log4j.debug(">>>>>> method name : " + methodsToInvoke[i].getName() + " para name : " + methodsToInvoke[i].getParameterTypes()[0].getName()); log4j.debug("======= >>>>>>> column name : " + metaData.getColumnName(i + 1) + " column type : " + metaData.getColumnClassName(i + 1)); break; } } } while(rs.next()) { Object obj = pojo.newInstance(); for(int i = 0; i < columnCount; i++) { methodsToInvoke[i].invoke(obj, new Object[]{castValue(rs.getObject(i + 1), methodsToInvoke[i].getParameterTypes()[0])}); } list.add(obj); } } catch (InstantiationException e) { e.printStackTrace(); log4j.error(e.getMessage(), e); } catch (IllegalAccessException e) { e.printStackTrace(); log4j.error(e.getMessage(), e); } catch (SQLException e) { e.printStackTrace(); log4j.error(e.getMessage(), e); } catch (IllegalArgumentException e) { e.printStackTrace(); log4j.error(e.getMessage(), e); } catch (InvocationTargetException e) { e.printStackTrace(); log4j.error(e.getMessage(), e); } catch (ClassNotFoundException e) { e.printStackTrace(); log4j.error(e.getMessage(), e); } } /** * 类型强制转换 * @param source * @param target * @return */ private static Object castValue(Object source, Class target) { if(source instanceof BigDecimal) { if(target == Long.class) return new Long(((BigDecimal)source).longValue()); else if(target == Integer.class) return new Integer(((BigDecimal)source).intValue()); else if(target == Short.class) return new Short(((BigDecimal)source).shortValue()); else if(target == Double.class) return new Double(((BigDecimal)source).doubleValue()); else if(target == Float.class) return new Float(((BigDecimal)source).floatValue()); } return source; }
然后在dao里实现了新的接口:
/** * jdbc sql查询,将记录注入POJO,结果集最终以list返回 * @param sql String sql语句 * @param params sql中的参数 * @param pojo String POJO的包路径 */ List sqlQueryAsPOJO(String sql, Object[] params, String pojo) throws SQLException;
哈哈,现在做多表连接查询简单多啦!
public ListgetPublicIndex(String startDate, String endDate) throws SQLException { StringBuffer sql = new StringBuffer(); sql.append("select a.id as id, a.money as deposit, b.money as loan, c.money as loanleave, a.tdate as tdate") .append(" FROM publicindex a inner join publicindex b") .append(" on a.tdate = b.tdate and a.flag = '1' and b.flag = '2'") .append(" inner join publicindex c") .append(" on a.tdate = c.tdate and c.flag = '3'") .append(" where (a.tflag = 2 or a.tflag = 3 or a.tflag = 7) and") .append(" (b.tflag = 2 or b.tflag = 3 or b.tflag = 7) and") .append(" (c.tflag = 2 or c.tflag = 3 or c.tflag = 7) and") .append(" a.tdate >= to_date(?, 'yyyy-mm-dd') and") .append(" a.tdate <= to_date(?, 'yyyy-mm-dd')") .append(" order by a.tdate"); return dao.sqlQueryAsPOJO(sql.toString(), new String[]{startDate, endDate}, "com.cuishen.edwview.pojo.Private"); }
新加的代码是对jdbc的简单封装,并没有用到hibernate,代码还不够通用,以后还要改进。