EclipseLink中的JPA静态元模型类在访问属性

时间:2015-09-01 09:42:38

标签: jpa intellij-idea eclipselink criteria-api metamodel

我在EclipseLink中生成静态元模型类时遇到问题。 在我的项目中,我首先使用以下方法为我的实体生成静态元模型:

1) org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor和IntelliJ IDEA    此类已生成为: target / generated-sources

然后我尝试在EclipseLink(GlassFish embedded)中使用这样的Hibernate生成的元模型类(例如下面),但是包含对metamodel属性的引用的代码行抛出 NullPointerException 异常:

 SingularAttribute<Employee, String> descriptionAttr = Employee_.description;
 predicates.add(criteriaBuilder.like(employee.get(descriptionAttr), "%" + description + "%"));

此处,emploee.get(&gt;&gt; null&lt;&lt;)抛出异常。

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Employee.class)
public abstract class Employee_ extends pl.salonea.entities.NaturalPerson_ {

    public static volatile SetAttribute<Employee, Skill> skills;
    public static volatile SetAttribute<Employee, ProviderService> suppliedServices;
    public static volatile SetAttribute<Employee, EmployeeRating> receivedRatings;
    public static volatile SingularAttribute<Employee, String> description;
    public static volatile SetAttribute<Employee, Education> educations;
    public static volatile SingularAttribute<Employee, String> jobPosition;
    public static volatile SetAttribute<Employee, TermEmployeeWorkOn> termsOnWorkStation;

}

2)接下来我认为这个元模型类可能是特定于实现的。所以我使用EclipseLink类似地生成它们 org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor target / generated-sources-eclipselink (如图所示)

IntelliJ IDEA EclipseLink static metamodel generation

最后,我有一个像metamodel这样的目录stracture:

enter image description here

3)我也在 build.gradle 这样的配置中使用,因为我认为在项目中包含这些生成的源:

if(hasProperty('jboss')) {
    sourceSets {
        main {
            java {
                srcDir 'target/generated-sources/'
            }
        }
    }
} else {
    sourceSets {
        main {
            java {
                srcDir 'target/generated-sources-eclipselink/'
            }
        }
    }
}

这样我想使用Hibernate生成的类与Jboss和EclipseLink生成的类与EclipseLink。

4)这样的配置只有在WilfFly / Hibernate上运行才有效,但在GlassFish / EclipseLink上没有这个 NullPointerException

5)在 persistence.xml 中,我有更多的EclipseLink生成使用这个属性用于一个持久性单元

<property name="eclipselink.canonicalmodel.subpackage" value="metamodel" />

和第二个持久性单元的这种属性(以避免重复冲突)

<property name="eclipselink.canonicalmodel.subpackage" value="metamodel_local" />

但我试图不使用这一代。它位于子包中,在我的代码中我只导入以前生成的元模型类。 原因是我想在Hibernate / Eclipse生成的同一命名空间元模型类中使用它们并适当地使用它们。 但是,如果Hibernate生成的元模型类也可以与EclipseLink一起使用,那么仅使用一代就不会有问题。

6)此外,我不能使用EclipseLink persistence.xml 属性生成的元模型类,因为每次运行/构建项目时它们都会重新生成。我需要在我的代码中手动修改两个元模型类,因为它们是从单个抽象元模型类继承而来的。在这里,我将重写在metamodel类的SetAttribute上的具有ConcreteType的子类AbstractType。

7)最后,我在使用元模型类配置运行集成测试时得到的错误

 Caused by: java.lang.NullPointerException
    at org.eclipse.persistence.internal.jpa.querydef.FromImpl.get(FromImpl.java:263)
    at pl.salonea.ejb.stateless.EmployeeFacade.findByMultipleCriteria(EmployeeFacade.java:295)
    at pl.salonea.ejb.stateless.EmployeeFacade.findByMultipleCriteria(EmployeeFacade.java:269)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
    at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
    at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
    at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
    at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:46)
    at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
    at sun.reflect.GeneratedMethodAccessor113.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
    at sun.reflect.GeneratedMethodAccessor141.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
    at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
    at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
    at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
    ... 149 more

4 个答案:

答案 0 :(得分:2)

- 我正在检查EclipseLink来源:

public <Y> Path<Y> get(SingularAttribute<? super X, Y> att){
    if (att.getPersistentAttributeType().equals(
            PersistentAttributeType.BASIC)) {
        return new PathImpl<Y>(
                this, this.metamodel, att.getBindableJavaType(),
                this.currentNode.get(att.getName()), att);
    } else {
        Class<Y> clazz = att.getBindableJavaType();
        Join join = new JoinImpl<X, Y>(
                this, this.metamodel.managedType(clazz),
                this.metamodel, clazz,
                this.currentNode.get(att.getName()), att);
        this.joins.add(join);
        return join;
    }
}

FromImpl.java:263是 if 语句的条件,因此看起来att.getPersistentAttributeType()返回null

如果您在https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EclipseLink上提交针对EclipseLink的错误,那将是件好事 组件是JPA。请将此描述复制粘贴并提供一些测试用例(使用此元模型的示例应用程序),让我们重现它并开发一些修复。

答案 1 :(得分:0)

即使使用2.7.4,我仍然面临着这个问题。

我真的很好奇AttributeProxyImpl.java中的以下方法。

public synchronized Attribute<X, T> getAttribute(){
    if (attribute == null){
        for (WeakReference<EntityManagerFactoryImpl> factoryRef: factories){
            EntityManagerFactoryImpl factory = factoryRef.get();
            if (factory != null){
                factory.getDatabaseSession();
            } else {
                factories.remove(factoryRef);
            }
        }
    }
    return attribute;
}

设置attribute字段的位置在哪里?

答案 2 :(得分:0)

问题可能出在初始化规范元模型失败。 您可以调查您的eclipselink日志以检查类似的内容:

mask1 = (m.ne(m.shift()).cumsum()[m]).value_counts().eq(3)
print (mask1)
3    False
1    False
dtype: bool

if mask1.any():
    print ('Butter and Jam missing in 3 consecutive rows')
else:
    print ('Butter and Jam are NOT missing in 3 consecutive rows')

就我而言,修复初始化后,NPE消失了。

答案 3 :(得分:-2)

我知道这是一张旧票,但我仍然想让你们知道我们如何解决这个问题。特别是最后一个nullpointer异常。

问题是,当您第一次使用Criteriabuilder时,您的entitimanager未加载。 要解决此问题,您可以在persistence.xml中设置以下内容

<property name="eclipselink.deploy-on-startup" value="true" />