--后记,本文所讲的实现在我的另一篇博客中提供了完整的源代码与编译好的JAR包,可供下载使用。http://lgdlgd.iteye.com/admin/blogs/619370
有经验的朋友都知道,列表查询时,一般不会查这个实体的全部字段,取部份字段的DetachedCriteria查询,常常 会用到AliasToBeanResultTransformer类把结果转换成POJO:
criteria.setResultTransformer(Transformers.aliasToBean(pojoClass));
但很显然,AliasToBeanResultTransformer类对结果集的封装是很简陋的,只能对本POJO的属性进行封装。
比如USER表有id,name,email,organization(组织,另一个实体),如果查询USER时要包含organization实体的name属性,但不要整个oganization,AliasToBeanResultTransformer就无能为力了,我写了另一个结果转换器来完成这个功能,其中用到OGNL工具包,Struts2和WEBWORK就是使用它把前台页面传回的参数填充ACTION里的属性对象的,我的灵感也是来源于此。
查询方法代码:
////////SERVICE中查询的方法
public List<User> findUsers(){
//要查的部份字段,ID,用户名和所在组织的名称
String[] columns = {"id","name","organization.name"};
//构造查询器
DetachedCriteria criteria = DetachedCriteria.forClass(User.class,"_user");
//筛选字段
DetachedCriteriaUntils.selectColumn(criteria,columns,Class pojoClass, String rootAlias,boolean forJoinTable);
//查询数据库
return userDAO.findByCriteria(criteria)
}
查询方法结束,下面这个方法就是如何筛选字段,不过只是部份代码,还有几个方法没有全列出,重点看最后几行
/**
* 该方法提供DetachedCriteria对查询字段的封装,
* 可支持无限级联取部分字段 ser.organization.parentOrganization.parentOrganization.orgName
* 但请注意1点 ,连接采用内联,级联越多,结果集可能就越少;
* @param columnNames
* 字符串数组,以数据的形式接收要查询的字段属性,如String[] column={"属性1","属性2","属性3"};
* @param pojoClass
* 实体类的Class,如Mobile.class;
* @param rootAials
* 为要查询的POJO对象指定一个别名
* @return DetachedCriteria 的一个对象,如果需要查询条件,在些对象后追加查询条件。
*
* @param forJoinTable 是否多表连接查询
*/
public static void selectColumn(DetachedCriteria criteria, String[] columnNames,
Class<? extends BaseModel> pojoClass, String rootAlias,boolean forJoinTable) {
if (null == columnNames) {
return;
}
//使用这个临时变量集合,是因为dinstinct关键字要放在最前面,而distinct关键字要在下面才决定放不放,
List<Projection> tempProjectionList = new ArrayList<Projection>();;
Set<String> aliases = getAliasFromRequest();
boolean hasJoniTable = false;
for (String property : columnNames) {
if(property.contains(POINT)){
String[] propertyChain = property.split("\\.");
if(aliases==null){aliases=new HashSet<String>(3);}
createAlias(criteria,rootAlias,aliases,propertyChain,0);
tempProjectionList.add(Projections.property(getAliasFromPropertyChainString(property)).as(property));
hasJoniTable = true;
}else{
tempProjectionList.add(Projections.property(rootAlias + POINT + property).as(property));
}
}
ProjectionList projectionList = Projections.projectionList();
if(hasJoniTable || forJoinTable || getHasJoinTatleFromRequest()){//这个一定要放在tempProjectionList的前面,因为distinct要在最前面
projectionList.add(Projections.distinct(Projections.id()));
}
for (Projection proj : tempProjectionList) {
projectionList.add(proj);
}
criteria.setProjection(projectionList);
if(!hasJoniTable){
criteria.setResultTransformer(Transformers.aliasToBean(pojoClass));
}else{//注意,重点就在这里,这里检测到如果有类类似于user.organization.name这种字段,就表示是级联其它表的部份字段,那么要使用下面的这个EscAliasToBean来转换结果集,而不能使用上面那个HIBERNATE提供的类
criteria.setResultTransformer(new EscAliasToBean(pojoClass));
}
}
本文主要不是讨论如何筛选字段,所以上面有部份方法没有再贴出来。下面是EscAliasToBean类的完整代码
package com.lgdlgd.hibernate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ognl.Ognl;
import org.hibernate.HibernateException;
import org.hibernate.transform.ResultTransformer;
import com.opensymphony.xwork2.util.InstantiatingNullHandler;
import com.opensymphony.xwork2.util.OgnlUtil;
/**
* 支持属性为自定义对象的结果集转换的部份属性查询
*/
@SuppressWarnings({"serial","unchecked"})
public class EscAliasToBean implements ResultTransformer {
private static final Map<String,Boolean> context = new HashMap<String,Boolean>(1);
static{
context.put(InstantiatingNullHandler.CREATE_NULL_OBJECTS, true);
}
/** POJO的class */
private final Class resultClass;
public EscAliasToBean(Class pojoClass) {
if(pojoClass==null) throw new IllegalArgumentException("resultClass cannot be null");
this.resultClass = pojoClass;
}
@Override
public List transformList(List collection) {
return collection;
}
/**
* 结果集转换
* @param tuple 属性值集合
* @param aliases 属性名集合,就是上面的{id,name,organization.name};
* @return 单个POJO实例--查询结果
*/
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
try {
Object root = resultClass.newInstance();
for (int i = 0; i < aliases.length; i++) {
Ognl.setValue(OgnlUtil.compile(aliases[i]), context, root, tuple[i]);
}
return root;
} catch (Exception e) {
throw new HibernateException(e.getMessage(),e);
}
}
}
到此完成,结果的转换比HIBERNATE的那个原生转换器还要简洁,本来这个类完全可以代替它的,只不过这个用到的其它的框架,牵连太多,功能虽强大,但恐在简单环境里速度不如原来的好。如果有朋友想要探讨如何筛选字段的部份,也可以提出来。
分享到:
相关推荐
- 数据库查询效率:为了提高性能,可以使用预编译的SQL语句(Hibernate的Criteria API或HQL的DetachedCriteria)。 - 视图的懒加载:避免一次性加载所有菜单,而是根据用户的交互动态加载需要的子菜单。 - 安全性...
综上所述,"Hibernate-基础联表模板"涵盖了Hibernate中关于联表查询的基础知识,包括各种查询方式、关联关系的定义、Fetch策略以及查询结果的处理等,是开发者进行数据库操作的有力助手。通过这个模板,开发者可以...
书中讲解了HQL的基本语法,包括选择、投影、连接、分组、排序等操作,以及查询结果的处理。此外,还介绍了Criteria API,一种更加面向对象的查询方式。 五、 Criteria与DetachedCriteria Criteria API提供了动态...
《孙卫琴精通Hibernate Part2》是一份深入学习Hibernate框架的教程,主要涵盖了该框架的高级特性和实战应用。在本教程的第二部分,我们将会更深入地探讨Hibernate的各个重要方面,帮助开发者提升数据库操作的效率和...
《深入浅出Hibernate》这本书是针对初学者设计的,旨在帮助读者快速掌握Hibernate这一流行的Java对象关系映射(ORM)框架。Hibernate是一个强大的工具,它简化了Java应用程序与数据库之间的交互,通过提供一种抽象...
- 查询缓存:缓存查询结果,提高效率。 9. **实体状态与生命周期** - 新建(Transient)、持久化(Persistent)、游离(Detached)、删除(Removed)四种状态。 - 生命周期转换:对象的保存、加载、更新和删除...
2. 移动对象:`DetachedCriteria`允许在不打开Session的情况下构建查询,然后在需要时再进行执行。 总之,Hibernate 3.2.2作为一款成熟且稳定的ORM框架,其丰富的功能和良好的社区支持使得它在众多项目中依然保持...
这份文档全面介绍了Hibernate框架,一个广泛使用的Java对象关系映射(ORM)工具,它允许开发者在Java应用中使用SQL数据库而无需直接编写SQL语句。下面我们将深入探讨该文档涵盖的主要知识点。 1. **Hibernate 概述*...
此外,`Criteria` API提供了一种类型安全的方式来构建动态查询,而`DetachedCriteria`则允许我们在不使用Session的情况下构建查询条件。 关联映射是Hibernate的另一个重要特性。`@OneToOne`、`@OneToMany`、`@...
3. **查询缓存**:存储查询结果,提高性能。 **八、高级特性** 1. **延迟加载(Lazy Loading)**:按需加载关联对象,避免加载大量无用数据。 2. **级联操作**:在操作主对象时,可以自动处理关联对象的增删改查。 ...
11. **Criteria API中的Projections**:用于定义查询结果的返回类型,如sum、avg、count等。 12. **SessionFactory**:是线程安全的,负责创建Session实例,一般在应用启动时初始化一次。 13. **第二级缓存**:...
通过Criteria、DetachedCriteria和Expression,我们可以构建复杂的查询条件。 6. **缓存机制**:Hibernate支持一级缓存(Session级别的)和二级缓存(SessionFactory级别的)。缓存可以提高性能,减少对数据库的...
14. **性能优化**:包括合理使用批处理、延迟加载、缓存、优化查询以及避免N+1查询问题等,都是提升Hibernate应用性能的关键。 15. **事务隔离级别**:理解数据库的四种事务隔离级别(读未提交、读已提交、可重复读...
10. **Criteria API与DetachedCriteria**:Criteria API用于在Session中执行查询,而DetachedCriteria则允许在Session之外构建查询条件,再在Session中执行。 11. **Criteria与HQL的比较**:两者都是ORM查询方式,...
Hibernate是一款开源的对象关系映射(ORM)框架,它允许开发者使用面向对象的编程方式来操作数据库,极大地简化了Java应用程序对数据库的操作。本备课笔记将深入探讨Hibernate的核心概念、配置、实体映射、查询语言...
8. ** Criteria API的DetachedCriteria**:DetachedCriteria允许预编译查询条件,适用于分页查询或延迟加载。 9. **懒加载与立即加载**:Hibernate支持懒加载(Lazy Loading),即关联对象只有在真正需要时才会被...
1. **Hibernate概述**:Hibernate是一个开放源代码的对象关系映射(ORM)框架,它自动管理Java应用程序与数据库之间的交互,将对象模型转换为关系数据库模型,简化了数据访问。 2. **配置文件**:Hibernate的工作...
《Hibernate中文文档》是针对Java开发人员的一份重要参考资料,它详细阐述了Hibernate框架的使用方法、API详解以及最佳实践。Hibernate是一个强大的对象关系映射(ORM)框架,它简化了Java应用程序对数据库的访问,...
《Hibernate开发指南》是一本专为Java开发者设计的详尽指南,旨在帮助他们掌握和熟练使用Hibernate这一强大的对象关系映射(ORM)框架。Hibernate是一个开源的Java库,它简化了数据库应用程序的开发,通过将Java类与...
- 查询缓存:对查询结果进行缓存,减少对数据库的访问。 7. 数据库连接池: - Hibernate可与多种数据库连接池集成,如C3P0、DBCP、HikariCP等,以提高数据库连接的复用性和系统性能。 8. 异常处理: - ...