1. 程式人生 > >使用Hibernate返回自定義型別時報錯的問題

使用Hibernate返回自定義型別時報錯的問題

資料庫為oracle,在使用Hibernate查詢時想要返回自定義的pojo型別,遇到型別轉換的異常。如下面的命名查詢希望返回資料行為typeClass型別

Query localQuery = session.getNamedQuery("findPersonInfo");
localQuery.setResultTransformer(Transformers.aliasToBean(typeClass)).list();//typeClass為目標pojo型別

執行後報錯,錯誤資訊如下:

java.lang.ClassCastException: com.test.pojo.TestPojo cannot be cast to java.util.Map
	at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102)
	at org.hibernate.transform.AliasToBeanResultTransformer.transformTuple(AliasToBeanResultTransformer.java:78)
	at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:75)
	at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:434)
	at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
	at org.hibernate.loader.Loader.list(Loader.java:2425)
	at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)
	at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2153)
	at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:987)
	at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)
	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)
TestPojo類如下:
public class TestPojo {
	private String id;
	private String username;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
}

原因是使用oracle時返回的欄位預設為大寫,導致轉換失敗。Hibernate可以通過自定義ResultTransformer類來解決這個問題,給出參考程式碼:

import java.lang.reflect.Field;
import java.util.List;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.hibernate.HibernateException;
import org.hibernate.transform.ResultTransformer;

/**
 * 
 * 修正hibernate返回自定義pojo型別時找不到屬性的BUG
 * 主要發生在使用oracle時,查詢返回的欄位預設是大寫的(除非SQL中指定了別名),這導致返回自定義pojo型別時會報找不到屬性的錯誤,該類用於修正此BUG。
 * 使用該類時SQL返回的欄位名大小寫或者帶"_"都會被忽略,如資料庫欄位為 USER_NAME,自定義pojo的屬性名為username就可以使用
 * 
 *
 */
public class IgnoreCaseResultTransformer implements ResultTransformer {

    private static final long serialVersionUID = -3779317531110592988L;

    private final Class<?> resultClass;
    private Field[] fields;
    private BeanUtilsBean beanUtilsBean;

    public IgnoreCaseResultTransformer(final Class<?> resultClass) {
        this.resultClass = resultClass;
        this.fields = this.resultClass.getDeclaredFields();
        beanUtilsBean=BeanUtilsBean.getInstance();
    }

    /**
     * aliases為每條記錄的資料庫欄位名,ORACLE欄位名預設為大寫
     * tupe為與aliases對應的欄位的值
     */
    public Object transformTuple(final Object[] tuple, final String[] aliases) {
        Object result;
		try {
			result = this.resultClass.newInstance();
			for (int i = 0; i < aliases.length; i++) {
				for (Field field : this.fields) {
					String fieldName = field.getName();
					//資料庫欄位帶下劃線的時候也能保證使用,如資料庫欄位為 USER_NAME,自定義pojo的屬性名為username就可以使用
					if (fieldName.equalsIgnoreCase(aliases[i].replaceAll("_", ""))) {
						beanUtilsBean.setProperty(result, fieldName, tuple[i]);
						break;
					}
				}
			}
		} catch (Exception e) {
			throw new HibernateException("Could not instantiate resultclass: " + this.resultClass.getName(), e);
		}
        return result;
    }

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

使用方法:

Query localQuery = paramSession.getNamedQuery("findPersonInfo");
localQuery.setResultTransformer(new IgnoreCaseResultTransformer(typeClass)).list();//typeClass為目標pojo型別

相關推薦

使用Hibernate返回定義型別時報的問題

資料庫為oracle,在使用Hibernate查詢時想要返回自定義的pojo型別,遇到型別轉換的異常。如下面的命名查詢希望返回資料行為typeClass型別 Query localQuery = session.getNamedQuery("findPersonInfo"

iView在定義主題時報 Inline JavaScript is not enabled. Is it set in your options?

報錯資訊如下:   ERROR in ./src/my-theme/index.less (./node_modules/[email protected]@css-loader!./node_modules/[email protected]@less

postgresql定義型別返回陣列

轉自 https://blog.csdn.net/victor_ww/article/details/44415895   create type custom_data_type as ( id int, name varchar(50), score decimal(

hibernate執行SQL返回定義Bean物件

16.2. 命名SQL查詢 可以在對映文件中定義查詢的名字,然後就可以象呼叫一個命名的HQL查詢一樣直接呼叫命名SQL查詢.在這種情況下,我們addEntity()方法. <sql-query > <return alias="person" class="eg.Person"/>

Effective C++讀書筆記----定義型別的傳參和返回值問題

對於自定義型別,傳參的時候儘可能的使用傳引用來代替傳值。 看如下這個例子: #include <iostream> using namespace std; #include <string> class Person {

使用Hibernate的XML配置來對映列舉型別,儲存定義型別資料

如今使用Hibernater作為ORM框架時,幾乎都是採用註解方式進行對映,可以對映任何型別欄位。這裡要說的是 對映列舉型別,在註解的方式下很容易(以後再補充),但是xml配置下就顯得麻煩一點。更復雜的一種對映,就是 列舉型別儲存到資料庫中的型別不是字串本

簡單定義VIEW報問題

nfc 定義 http dnf androi dem and .com android aNDROIDNFC%E8%AF%BB%E5%8D%A1%E5%99%A8%E7%9A%84DEMO http://music.baidu.com/songlist/495819911

定義型別 結構體型別建立 結構體初始化

結構體 結構體的基礎知識: 結構是一些值的集合,這些值稱為成員變數。結構的每個成員可以是不同型別的變數。 結構體的宣告: struct tag //struct是結構體關鍵字,tag為結構體標籤 { member-list; //成員列表 }variable-list;//變

Qt中QVariant儲存定義型別

#include <QDebug> //先宣告類 class Test{ public: QString myName; }; //註冊自定義型別 Q_DECLARE_METATYPE(Test) int main(int argc, char *argv[]) {

定義型別的建立

建立自定義型別的最常見方式,就是組合使用建構函式模式與原型模式。 1 window.onload = function() { 2 var person1 = new Person("Nicholas", 29, "Software Engineer"); 3 var perso

JAVA 排序定義型別元素集合

排序程式碼 public class Collection_sort3 { public static void main(String[] args) { List <Points> list = new ArrayList<Points&g

Spring Data Jpa框架定義查詢語句返回定義實體的解決方案

在使用Spring Data Jpa框架時,根據業務需求我們通常需要進行復雜的資料庫查詢,並返回我們自定義的實體類,而在該框架下,目前僅僅支援返回與資料庫對映進行持久化的POJO實體。雖然在框架上我們可以使用@Query註解執行我們自定義的sql語句,但是其返回值為List<Object[

Hadoop定義型別處理手機上網日誌

job提交原始碼分析 在eclipse中的寫的程式碼如何提交作業到JobTracker中的哪? (1)在eclipse中呼叫的job.waitForCompletion(true)實際上執行如下方法   connect();   info = jobClient.submitJobInt

定義型別轉換器

1. 繼承DefaultTypeConverter(實現了ognl.TypeConverter介面)。修改如下方法: public Object convertValue(Map<String, Object> context, Object value, Class toType)

Android進階AIDL使用定義型別

原文首發於微信公眾號:jzman-blog,歡迎關注交流! 上篇文章中主要介紹從 AIDL 的使用方式以及 Android 開發中不同程序之間的通訊,遺留的問題是如何在 AIDL 中使用自定義型別,具體步驟如下: 1. 建立自定義型別 2. 宣告自定義型別 3.

8.引數繫結-定義型別(傳智播客)

需求:自定義日期型別引數繫結 private Date itemCreateDate; 如果controller形參pojo物件的屬性中有日期型別,需要自定義引數繫結。 將請求日期資料串轉換成日期型別,要轉換的日期型別和pojo中日期屬性的型別保持一致。所以自定義引數繫結將

Object型別轉換成定義型別(向下轉型)

Object型別轉換成自定義型別 場景:   從資料庫或者別的途徑接收物件的時候用Object,但是用的時候怎麼object點(方法提示 | alt+'/'),都點不出自定義型別的方法。   比如,資料庫查詢Customer的時候,用Object來接收,那麼想要呼叫Customer中的getCust_I

JAVA高階基礎(10)---TreeSet對定義型別進行定製排序及增強for迴圈遍歷集合

TreeSet 自然排序 對於自定義型別,那麼要實現自然排序,需要去 Comparable 介面中的 compareTo 方法。在 compare To 方法中我們可以根據自己的業務要求,來實現自己的排序規則。 定製排序     在建立容器

springMVC定義型別轉換器(date型別轉換)

//日期的月份不能寫成小寫mm,因為在日期中還有分鐘mm,這兩者不能相同。 1.建立一個類實現Convert介面,實現convert方法 public date convert(String source){   if(source!=null&&!source.equals(""){

Android 定義型別檔案與程式關聯

0x01 功能  實現在其他應用中開啟某個字尾名的檔案 可以直接跳轉到本應用中的某個activity進行處理   0x01 實現    首先建立一個activity ,然後在manifest裡對該activity項編輯,加入    <intent-