您的位置:首页 > 其它

Hibernate高级使用:查询返回自定义对象

2010-11-19 13:54 603 查看
在使用Hibernate的使用中,对报表的数据处理经常需要写原生的SQL,但使用默认的Hibernate中的List方法只能返回值数组对象,这给以后的修改和维护带来很多的不便。

其实我们可以通过扩展Hibernate让结果封装为指定的对象结果集,这样即使用原生SQL,也可能以优雅的方式来处理返回的结果。

Hibernate中有一系列用于组装返回值对象的工具类,这些类位于Package:org.hibernate.transform中,当Hibernate查询后会通过这些Transform来重新组装原始的返回结果,我们只需要自定义一个这样的Transform,然后在查询时把这个Transform传递给Hibernate的查询方法,即可把我们指定的方法来重新组装查询结果。

为了实现这个功能,我们需要实现org.hibernate.transform.ResultTransformer这个接口。

接口包括两个方法:

java.lang.Object transformTuple(java.lang.Object[] objects, java.lang.String[] strings);

java.util.List transformList(java.util.List list);


transformTuple方法参数说明:

1: 值列表。原始SQL查询后的返回值数组。

2: 列别名列表。原始SQL查询结果返回的列名(这个需要注意,Oracle等DB可能不区分大小写,所以在通过列名反射取得对象类的Set方法前,如果需要按驼峰式的命名法,需要自己制定别名规则)。

transformList方法一般直接返回参数List。

/**
* Convert query result to vo list util class.
*/
class AliasToBeanResultTransformer implements ResultTransformer {
private static final long serialVersionUID = -5199190581393587893L;
private final Class<T> resultClass;
private Setter[] setters;
private PropertyAccessor propertyAccessor;
public AliasToBeanResultTransformer(Class<T> resultClass) {
if (resultClass == null) throw new IllegalArgumentException("resultClass cannot be null");
this.resultClass = resultClass;
propertyAccessor = new ChainedPropertyAccessor(new PropertyAccessor[]{PropertyAccessorFactory.getPropertyAccessor(resultClass, null), PropertyAccessorFactory.getPropertyAccessor("field")});
}
public Object transformTuple(Object[] tuple, String[] aliases) {
Object result;
try {
if (setters == null) {
setters = new Setter[aliases.length];
for (int i = 0; i < aliases.length; i++) {
String alias = convertColumnToProperty(aliases[i]);
if (alias != null) {
try {
setters[i] = propertyAccessor.getSetter(resultClass, alias);
} catch (PropertyNotFoundException e) {
continue;
}
}
}
}
result = resultClass.newInstance();
for (int i = 0; i < aliases.length; i++) {
if (setters[i] != null) {
setters[i].set(result, tuple[i], null);
}
}
} catch (InstantiationException e) {
throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName());
} catch (IllegalAccessException e) {
throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName());
}
return result;
}
/**
* Converts the specified 'XXX_YYY_ZZZ'-like column name to its
* 'xxxYyyZzz'-like Java property name.
*
* @param columnName the column name
* @return the Java property name
*/
public String convertColumnToProperty(String columnName) {
columnName = columnName.toLowerCase();
StringBuffer buff = new StringBuffer(columnName.length());
StringTokenizer st = new StringTokenizer(columnName, "_");
while (st.hasMoreTokens()) {
buff.append(StringUtils.capitalize(st.nextToken()));
}
buff.setCharAt(0, Character.toLowerCase(buff.charAt(0)));
return buff.toString();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public List<T> transformList(List collection) {
return collection;
}
}


上面参考代码中使用field_name作为别名规则,这样在返回对象定义时,可以定义属性为fieldName,相应的Set方法名为SetFieldName。

**
需要注意的是, 这种方法需要返回的对象类属性类型定义需要和DB返回的相应字段类型兼容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐