`
buptchenliang
  • 浏览: 4785 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Hibernate在from子句中使用子查询

阅读更多
    最近用到了Hibernate来作为数据处理部分的框架,离线criteria的确很好用,但在分页上确实让人头疼。要想分页就需要记录的总条数,如果只是一般的查询只需要
criteria.setProjection(Projections.rowCount());

就可以了,但如果是distinct的查询,记录条数和你所需查询的列有关,那么可以这样
Projections.countDistinct(propertyName);

问题来了,好像只能有一列啊。没错在标准sql中的distinct count也只能是一列的,但当有多列查询的时候怎么办呢?criteria有个接口可以设定结果值为distinct,就这样
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

但是这样做的问题在于,他是先执行,后在程序中distinct,这样会导致每页的记录可能不同,而且性能低下。
换个思路在写sql的时候可以这样写
select count(*) from (select distinct xxxxxx)

也就是说在外层套一个count 而真实的查询语句在from子句中,成为一个子查询。那看看如何变成Hibernate的形式吧。我在网站上搜索了好久,终于得出一个结论(经过Hibernate文档证明了)Hibernate不支持from子句中存在子查询,他们认为from应该是一个映射了的对象,子查询和他们的思想不符。
好吧,那再换个思路,Hibernate本身只是一个映射的过程,那么实际执行还是需要JDBC实现。如果是JDBC就需要sql语句,我们把criteria中蕴含的sql语句提取出来,然后加上我们外层的计数部分,然后再像Hibernate一样绑定参数就可以了,因为外层没有参数占位符,所以也不会影响Hibernate按位置绑定参数,因为没有接口,那只能读源码了。果然,hibernate最后通过sql(就是log中看到的那个)生成一个PreparedStatement,并通过方法绑定参数。废话少说,直接来个破冰之旅。
	/**
	 * 因为需要修改sql,就要传入你新的sql,criteria必须是绑定session的
	 * 因为我们用到了session
	 * @param sql
	 * @param criteria
	 * @return
	 */
	public static List<List> wrapAndExecute(String sql, Criteria criteria) {
		ResultSet rs = null;//最后的结果集
		PreparedStatement ps = null;//我们自己的PreparedStatement
		Connection connection = null;//session中获取的连接
		try {
			//先转型
			CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
//			获取SessionImplementor类型的session
			SessionImplementor session = criteriaImpl.getSession();
//			获取factory
			SessionFactoryImplementor factory = session.getFactory();
//			获取CriteriaQueryTranslator对象,按照Hibernate源码中的方式生成
			CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, criteriaImpl, criteriaImpl
					.getEntityOrClassName(), CriteriaQueryTranslator.ROOT_SQL_ALIAS);
//			从CriteriaQueryTranslator对象中获取保存参数的QueryParameters对象
			QueryParameters queryParameters = translator.getQueryParameters();
//			从factory中获取implementors,一般只用一个
			String[] implementors = factory.getImplementors(criteriaImpl.getEntityOrClassName());
//			因为只用一个,所以只需要一个loader,按照Hibernate源码中的方式新建
//			注意有些地方由于非public所以需要用反射,反射部分代码就不贴了,注意invokeMethod要从子类找到父类,直到object
//			因为有些方法是写在父类中的
			Loader loader = new CriteriaLoader((OuterJoinLoadable) ReflectUtil.invokeMethod(session,
					"getOuterJoinLoadable", new Class[] { String.class }, new Object[] { implementors[0] }), factory,
					criteriaImpl, implementors[0], ((SessionImpl) session).getLoadQueryInfluencers());
//			按照Hibernate源码方法获取walker
			CriteriaJoinWalker walker = new CriteriaJoinWalker((OuterJoinLoadable) factory
					.getEntityPersister(implementors[0]), translator, factory, criteriaImpl, criteriaImpl
					.getEntityOrClassName(), session.getLoadQueryInfluencers());
//			获取了criteria的sql
			String criteriaSql = walker.getSQLString();			
//			用传入的sql代替,注意PLACEHOLDER代表criteriaSql的占位符
			sql = sql.replace(PLACEHOLDER, criteriaSql);
//			获取session中的连接
			connection = session.getJDBCContext().getConnectionManager().getConnection();
//			构建新的PreparedStatement
			ps = connection.prepareStatement(sql);
//			注意一定要过滤过参数才能绑定
			queryParameters.processFilters(criteriaSql, session);
//			通过反射绑定参数
			ReflectUtil.invokeMethod(loader, "bindParameterValues", new Class[] { PreparedStatement.class,
					QueryParameters.class, int.class, SessionImplementor.class }, new Object[] { ps, queryParameters,
					1, session });
//			获取结果集
			rs = session.getBatcher().getResultSet(ps);
......

呼,好了,终于抠出了criteria的东西了。
最后值得注意的是,由于ResultSet和PreparedStatement是自己创建的,所以需要自己维护,就是要注意关闭咯。至于connection由于是session中获取的,可以不用管,否则这个session如果还有其他操作connection关了就要抛错了。
0
0
分享到:
评论
2 楼 buptchenliang 2012-09-05  
liuluoqiu 写道
lz,这样是可以获得原生sql,但是里面的参数是?,如何才能显示?中内容啊

本文目的不是获取完全的sql,只是通过这种方式个性化sql。当然你想获取到完整的sql也是可以的,所有的参数都在QueryParameters 这个类里,你完全可以从这个对象中将每个参数获取,结合带有?的sql就可以得到完整的sql了。
1 楼 liuluoqiu 2012-06-15  
lz,这样是可以获得原生sql,但是里面的参数是?,如何才能显示?中内容啊

相关推荐

    hibernate子查询

    关于在hibernate查询中如何在from子句中使用子查询

    最全Hibernate 参考文档

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. select子句 14.5. 聚集函数 14.6. 多态查询 14.7. where子句 14.8. 表达式 14.9. order by子句 14.10. group by子句 14.11. 子查询 14.12. HQL示例 14.13...

    Hibernate+中文文档

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 ...

    Hibernate中文详细学习文档

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 ...

    hibernate3.2中文文档(chm格式)

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 ...

    Hibernate 中文 html 帮助文档

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 14.12. 子...

    HibernateAPI中文版.chm

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 ...

    Hibernate3+中文参考文档

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. select子句 14.5. 聚集函数 14.6. 多态查询 14.7. where子句 14.8. 表达式 14.9. order by子句 14.10. group by子句 14.11. 子查询 14.12. HQL示例 14.13...

    hibernate 体系结构与配置 参考文档(html)

    from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 14.12....

    Hibernate教程

    15.2. from子句 15.3. 关联(Association)与连接(Join) 15.4. select子句 15.5. 聚集函数 15.6. 多态查询 15.7. where子句 15.8. 表达式 15.9. order by子句 15.10. group by子句 15.11. 子查询 15.12. HQL...

    hibernate3.04中文文档.chm

    15.2. from子句 15.3. 关联(Association)与连接(Join) 15.4. select子句 15.5. 聚集函数 15.6. 多态查询 15.7. where子句 15.8. 表达式 15.9. order by子句 15.10. group by子句 15.11. 子查询 15.12. HQL...

    hibernate 教程

    子查询 11.12. HQL示例 11.13. 提示和技巧(Tips & Tricks) 12. 条件查询(Criteria Query) 12.1. 创建一个Criteria实例 12.2. 缩小结果集范围 12.3. 对结果排序 12.4. 关联(Associations)...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 ...

    hibernate 框架详解

    from子句 15.3. 关联(Association)与连接(Join) 15.4. select子句 15.5. 聚集函数 15.6. 多态查询 15.7. where子句 15.8. 表达式 15.9. order by子句 15.10. group by子句 15.11. 子查询 15.12. HQL示例 ...

    Hibernate参考文档

    14.2. from子句 14.3. 关联(Association)与连接(Join) 14.4. join 语法的形式 14.5. select子句 14.6. 聚集函数 14.7. 多态查询 14.8. where子句 14.9. 表达式 14.10. order by子句 14.11. group by子句 14.12. 子...

    hibernate

    子查询 11.12. HQL示例 11.13. 提示和技巧(Tips & Tricks) 12. 条件查询(Criteria Query) 12.1. 创建一个Criteria实例 12.2. 缩小结果集范围 12.3. 对结果排序 12.4. 关联(Associations)...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    11.3.4 查询中使用构造器 464 11.3.5 使用distinct排除相同的记录 465 11.3.6 where子句和条件表达式 466 11.3.7 使用JPQL函数 466 11.3.8 多态查询 467 11.3.9 关联和连接 469 11.3.10 使用order by进行结果排序 ...

    NHibernate中文帮组文档(2008.11月更新)

    12.2. from子句 12.3. 关联(Association)与连接(Join) 12.4. select子句 12.5. 聚集函数 12.6. 多态查询 12.7. where子句 12.8. 表达式 12.9. order by子句 12.10. group by子句 12.11. 子查询 12.12. HQL示例 12.13...

    NHibernate参考文档 2.0.0 chm

    12.2. from子句 12.3. 关联(Association)与连接(Join) 12.4. select子句 12.5. 聚集函数 12.6. 多态查询 12.7. where子句 12.8. 表达式 12.9. order by子句 12.10. group by子句 12.11. 子查询 12.12. HQL示例 12.13...

Global site tag (gtag.js) - Google Analytics