我需要动态查找作为 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/