java - 在 JPA 实体上查找声明的 java.util.Map 字段的泛型类型时出现 ClassNotFoundException (GlassFish 3)

标签 java jpa reflection glassfish classloader

我需要动态查找作为 JPA 实体上声明字段的 java.util.Map 子类型实例的类,这里是 details 映射中的 EventDetail 实例:

@Entity
@Table( name = "EVENTS" )
public class Event implements Serializable
{
    ...

    @OneToMany( mappedBy = "event", fetch = FetchType.LAZY )
    @MapKey( name = "key" )
    private Map<String, EventDetail> details;

    ...

    public Map<String, EventDetail> getDetails()
    {
        return ( this.details );
    }

    ...
}

EventDetail 没什么特别的:

@Entity
@Table( name = "EVENT_DETAILS" )
public class EventDetail implements Serializable
{
    private static final long serialVersionUID = -1425743343118085745L;

    @Id
    @Column( name = "EVENT_DETAIL_ID" )
    private Long              id;

    @ManyToOne( fetch = FetchType.EAGER, optional = false )
    @JoinColumn( name = "EVENT_ID", referencedColumnName = "EVENT_ID" )
    private Event             event;

    ...
}

假设映射是正确的。要处理的代码位于 CDI bean 中,如下所示:

// clazz is the one declaring the map: find generic type (of value)!
ParameterizedType mapType = ( ParameterizedType ) clazz.getDeclaredField( "details" ).getGenericType();
Type mapValueType = mapType.getActualTypeArguments()[1]; // get EventDetail type

Class<?> mapValueClass = Class.forName( mapValueType.toString() ); // FAIL: CNFE!
// Class<?> mapValueClass = Class.forName( mapValueType.toString(), true, EventDetail.class.getClassLoader() );
// Class<?> mapValueClass = Class.forName( mapValueType.toString(), true, clazz.getClassLoader() );
// Class<?> mapValueClass = Class.forName( mapValueType.toString(), true, Thread.currentThread().getContextClassLoader() );

Method mapGetMethod = method.getReturnType().getMethod( "get", Object.class );

methods.add( mapGetMethod );

// set return type to whatever the map defines
clazz = mapValueClass;

调用任何 Class.forName() 变体时,我收到 ClassNotFoundException:

java.lang.ClassNotFoundException: class tld.company.compliance.coiresultmgmt.entity.EventDetail
    at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1509)
    at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1359)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:270)
    at tld.company.coi.resultmgmt.view.BaseEventHistoryManager.getHistoryStringValuesFor(BaseEventHistoryManager.java:926)
.
.
.

问: 我究竟做错了什么?我如何获得类(class)?

这是在 GlassFish 3.2.1 环境中。使用 EclipseLink 2.3 作为 JPA 提供程序。

最佳答案

问题是 Type.toString() 在实际类名之前输出 "class ",例如 "class tld.company.compliance.coiresultmgmt。实体.EventDetail”。这显示在堆栈跟踪中,但很容易被忽视。

您当然需要删除该部分,例如喜欢

String typeString = mapValueType.toString();

// cut type from type string, otherwise CNFE!
Class<?> mapValueClass = Class.forName( typeString.substring( typeString.indexOf( ' ' ) + 1 ) );

关于java - 在 JPA 实体上查找声明的 java.util.Map 字段的泛型类型时出现 ClassNotFoundException (GlassFish 3),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26723277/

相关文章:

java - 使用 lift-json 根据 json 和元数据实例化一个类型

java - 如何从 URL 下载 .jar 文件

java - 如何即时修改 java 属性?

java - POJO 对象的 JAX-RS 通用工厂

java - Java 中的解释性语言以及对 Java 方法的调用

java - HibernateTransactionManager 或 JpaTransactionManager

java - 将对象属性列表加入字符串

java - 连接请求响应处理

java - CombinedDomainXYPlot 不重新缩放域轴

mysql - 使用 JPA Hibernate 将 EXCEL 工作表映射到数据库