2014-01-30 88 views
4

我們正在從MyBatis遷移到Spring Data JPA(使用hibernate)。最初,Spring配置將特定域級對象的util:map指定爲由枚舉鍵引用的值。因此地圖被注入到服務級別類別中。然後使用此映射在流程流程中基於特定的枚舉來獲取域級對象。現在我們重構了服務層以使用Spring Data啓用的@Entity域級對象,當我們嘗試使用枚舉鍵獲取實體的實例時,它會返回代理(如您所期望的那樣)。因此,當我們嘗試並使用返回的實例時,我們得到一個ClassCastException(由java.lang.ClassCastException:com.sun.proxy引起。$ Proxy43不能轉換爲com.ourpackage.Event)。我的問題是:如何將@Entity類注入到util:map配置中,以便可以設置更多的屬性?Spring Data JPA - 具體實體類的依賴注入

這裏是實體對象和枚舉查找鍵地圖的配置:

<?xml version="1.0" encoding="UTF-8"?> 
    <beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd"> 

    <!--*********************************************************************--> 
    <!-- Event bean definitions --> 
    <!--*********************************************************************--> 
    <bean id="workEvent" class="com.ourpackage.Event"> 
     <constructor-arg name="action" type="java.lang.String" value="action"/> 
     <constructor-arg name="type" type="java.lang.String" value="type"/> 
     <constructor-arg name="description" type="java.lang.String" value="A description"/> 
    </bean> 

    <!--*********************************************************************--> 
    <!-- Event Maps --> 
    <!--*********************************************************************--> 
    <util:map id="workEvents" map-class="java.util.HashMap" key-type="com.anotherpackage.EventType" value-type="com.ourpackage.Event"> 
     <entry> 
      <key><value type="com.anotherpackage.EventType">WORK_ITEM</value></key> 
      <ref local="workEvent"/> 
     </entry> 
    </util:map> 
</beans> 

這裏是實體域類定義:

package com.ourpackage; 

import static javax.persistence.GenerationType.IDENTITY; 
import static javax.persistence.TemporalType.TIMESTAMP; 

import java.util.Date; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 
import javax.persistence.Temporal; 

import org.apache.commons.lang.builder.ToStringBuilder; 
import org.apache.commons.lang.builder.ToStringStyle; 
import org.springframework.transaction.annotation.Transactional; 

import com.basepackage.ServiceEntity; 

/** 
* The Class Event. 
* 
*/ 
@Entity 
@Table(name = "events") 
@Transactional(readOnly = true) 
public class Event extends ServiceEntity { 
    .... 
} 

這裏是從服務類的代碼使用此地圖:

// The following line produces the ClassCastException 
workEvent = workEvents.get(EventType.WORK_ITEM); 

這當然可以通過報廢de懸置注入配置,並簡單地構建Event類,但配置是首選方法。

任何幫助將不勝感激。

+0

你從哪個類獲得哪個ClassCastException?我認爲com.ourpackage.Event是workEvent的類型? – Koitoer

+0

Ho Koitoer,我在上面的例子中改變了軟件包的名稱,而不是使用真實的信息。我們有一個使用注入的workEvents HashMap的命令類: workEvent = workEvents.get(EventType.WORK_ITEM); 正是在這個關頭,我們得到了ClassCastException。異常本身如下: 引起:java.lang.ClassCastException:com.sun.proxy。$ Proxy43不能轉換爲com.ourpackage.Event 所以問題是Spring注入workEvent的方式在因爲它作爲代理被返回。 – redders

+0

您是否嘗試轉換爲接口,而不是類轉換異常? –

回答

3

問題是具體類不再是com.ourpackage.Event,因爲Spring在其中包含com.sun.proxy.$Proxy43類型的代理,並且不能將代理強制轉換爲事件,因爲它們是兩種完全不同的類型。

爲了解決這個問題,使事件實現一個接口並將其轉換爲該接口,而不是轉換爲具體的類。

一般來說,在大量使用代理/ AOP(如Spring/Hibernate應用程序)的應用程序中,避免轉換爲具體類型是一種很好的做法。