Spring Data JPA - 具体实体类的依赖注入

时间:2014-01-30 11:48:57

标签: spring jpa spring-data-jpa classcastexception

我们正在从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配置中,以便设置更多属性?

以下是实体对象和枚举查找键的映射配置:

<?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);

当然可以通过废弃依赖注入配置并简单地动态构建Event类来解决这个问题,但是配置是首选方法。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

问题是具体类不再是com.ourpackage.Event,因为Spring在其中包含了com.sun.proxy.$Proxy43类型的代理,并且不可能将代理转换为事件,因为它们是两个完全不同的类型。

要解决此问题,请将事件实现为接口并强制转换为该接口,而不是强制转换为具体类。

通常,在大量使用代理/ AOP(如Spring / Hibernate应用程序)的应用程序中避免转换为具体类型通常是一种很好的做法。