您的位置:首页 > 数据库

由将SQL查询结果转化为pojo的想到的

2009-10-26 11:52 357 查看
今天在网上上看见一篇“将SQL查询结果转化为pojo对象的”博客,博主自定义做了一个类如下:

import java.lang.reflect.Field;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.property.ChainedPropertyAccessor;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.property.Setter;
import org.hibernate.transform.ResultTransformer;

/**
* 完成native sql查询数据(数组)到pojo对象的转化
* @author warison
*
* Oct 26, 2009
*/
public class PojoTransformer implements ResultTransformer {
private static final long serialVersionUID = 1L;
private Class<? extends BaseModel> resultClass;
private Setter[] setters;
private PropertyAccessor propertyAccessor;

public PojoTransformer(Class<? extends BaseModel> 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")});
}

//结果转换时,HIBERNATE调用此方法
public Object transformTuple(Object[] tuple, String[] aliases) {
Object result;

try {
if(setters==null) {//首先初始化,取得目标POJO类的所有SETTER方法
setters = new Setter[aliases.length];
for (int i = 0; i < aliases.length; i++) {
String alias = aliases[i];
if(alias != null) {
//我的逻辑主要是在getSetterByColumnName方法里面,其它都是HIBERNATE的另一个类中COPY的
//这里填充所需要的SETTER方法
setters[i] = getSetterByColumnName(alias);
}
}
}
result = resultClass.newInstance();

//这里使用SETTER方法填充POJO对象
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;
}

//根据数据库字段名在POJO查找J***A属性名,参数就是数据库字段名,如:USER_ID
private Setter getSetterByColumnName(String alias) {
//取得POJO所有属性名
Field[] fields = resultClass.getDeclaredFields();
if(fields==null || fields.length==0){
throw new RuntimeException("实体"+resultClass.getName()+"不含任何属性");
}
//把字段名中所有的下杠去除
String proName = alias.replaceAll("_", "").toLowerCase();
for (Field field : fields) {
if(field.getName().toLowerCase().equals(proName)){//去除下杠的字段名如果和属性名对得上,就取这个SETTER方法
return propertyAccessor.getSetter(resultClass, field.getName());
}
}
throw new RuntimeException("找不到数据库字段 :"+ alias + " 对应的POJO属性或其getter方法,比如数据库字段为USER_ID或USERID,那么J***A属性应为userId");
}

@SuppressWarnings("unchecked")
public List transformList(List collection) {
return collection;
}
}





public class PojoUser extends BaseModel {
private String pwd;
private String userName;
private String userId;

public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}

测试方法:

String queryString="select user_id userId,user_name userName from oa_user";

SQLQuery query = sessionFactory.openSession().createSQLQuery(queryString);

query.setResultTransformer(new PojoTransformer(pojoClass));

query.list();

看到这里,容易想到,hiernate3.2以后好像已经支持这种方法


SQLQuery query = sessionFactory.openSession().createSQLQuery(queryString);
query.addScalar("userName", Hibernate.STRING);
query.setResultTransformer(Transformers.aliasToBean(pojoClass));

System.out.println(((PojoUser)list.get(0)).getUserName());

结果发现如果query.addScalar("userName", Hibernate.STRING);定义为

query.addScalar("userId", Hibernate.STRING);

打印的结果就是null(实际上是存在值的),不尽感动hiernate的愚蠢,难道没有设置全部属性(或当前查询对应属性的方法吗),如果像hiernate的做,岂不是要将所有查询的属性都设置一次query.addScalar。

看到这里可能你会用query.addEntity(PojoUser.class);反驳我,可以使用query.addEntity(PojoUser.class);前提是PojoUser.class已经做了映射。

相比下,上面博主的方法还算是可行。

类似问题,很容易让我想到ibtatis的处理方式,弄过ibatis的人都晓得,累世的问题简直就是小菜。

到这里不尽想说一句“不要迷恋Hibernate,Hibernate只是一传说。。。” 。毕竟hiernate的最终目标是hql查询支持,对于sql的支持可能还是存在一定的缺陷。o(∩_∩)o...哈哈
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: