今天在網上上看見一篇“將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尋找JAVA屬性名稱,參數就是資料庫欄位名,如: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,那麼JAVA屬性應為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...哈哈