Spring中的数据JPA NPE在validateQuery中使用自定义entityManagerFactory和Query注释

时间:2015-02-11 15:56:04

标签: java spring hibernate spring-boot spring-data

我正在使用spring-boot-starter-parent 1.2.0.RELEASE开发一个Spring Boot项目。我正在尝试通过spring SpringJtaSessionContext扩展来配置spring以使用Hibernate的JTASssionContext。

在我的@Configuration课程中,我将返回配置为LocalContainerEntityManagerFactoryBean的JTA。

@Configuration
@EnableJpaRepositories(repositoryFactoryBeanClass = JpaRepositoryFactoryBean.class)
@EntityScan(basePackageClasses = Event.class)
public class JPAConfig {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private JpaVendorAdapter jpaVendorAdapter;

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
        LocalContainerEntityManagerFactoryBean   localContainerEntityManagerFactoryBean = new    LocalContainerEntityManagerFactoryBean();
        localContainerEntityManagerFactoryBean.setJtaDataSource( dataSource  );
        localContainerEntityManagerFactoryBean.setJpaVendorAdapter( jpaVendorAdapter );
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.current_session_context_class", "jta");
        properties.put("javax.persistence.transactionType", "JTA");
        properties.put( "hibernate.dialect", "org.hibernate.dialect.SQLServerDialect" );
        properties.put( "hibernate.format_sql", "true" );
        properties.put( "hibernate.ejb.naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy");
        localContainerEntityManagerFactoryBean.setJpaPropertyMap( properties );
        return localContainerEntityManagerFactoryBean;
    }

}

似乎所有东西都已连线,但我遇到了org.springframework.data.jpa.repository.query.SimpleJpaQuery

内的NPE
/**
 * Validates the given query for syntactical correctness.
 * 
 * @param query
 * @param em
 */
private final void validateQuery(String query, String errorMessage) {

    if (getQueryMethod().isProcedureQuery()) {
        return;
    }

    EntityManager validatingEm = null;

    try {
        validatingEm = getEntityManager().getEntityManagerFactory().createEntityManager();
 ....

getEntityManager().getEntityManagerFactory().createEntityManager();的调用导致NPE似乎来自createEntityManager()

getEntityManager()提供的类似乎是我在JPAConfig中定义的LocalContainerEntityManagerFactoryBean。提供的EntityManagerFactory似乎是org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean。似乎createEntityManager()内部的东西是空的。

这导致以下stacktrace

    Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract com.vnomicscorp.dw.model.Event com.vnomicscorp.dw.webservice.repo.EventRepository.findByCompositeKey(com.vnomicscorp.dw.model.Vehicle,com.vnomicscorp.dw.model.EventType,long)!
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:87)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:57)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:70)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:51)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:137)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:202)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:80)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:357)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:192)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
    ... 240 more
Caused by: java.lang.NullPointerException
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:76)
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:118)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1602)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:210)
    at org.hibernate.jpa.internal.EntityManagerImpl.<init>(EntityManagerImpl.java:91)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:345)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
    at sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:388)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:541)
    at com.sun.proxy.$Proxy76.createEntityManager(Unknown Source)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:80)
    ... 253 more

由line引起的是指向此方法的反射调用

    Object retVal = method.invoke(this.nativeEntityManagerFactory, args);

我还应该补充一点,我正在使用Spring数据休息,并且还有一个RepositoryRestMvcConfiguration类。

@Configuration
public class RestRepoConfig extends RepositoryRestMvcConfiguration {

    @Override
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(Employee.class, Vehicle.class, Customer.class, VehicleMake.class, VehicleModel.class, Event.class);
    }
}

在尝试使用添加的方法验证PagingAndSortingRepository时,会抛出NPE。

public interface EventRepository extends PagingAndSortingRepository<Event, Long> {

    @Query("SELECT e FROM Event AS e WHERE e.vehicle = :vehicle AND e.startTime <= :endTime AND e.endTime >= :startTime")
    public Iterable<Event> findByTimeperiod(@Param("vehicle") Vehicle vehicle,
                                        @Param("startTime") long startTime,
                                        @Param("endTime") long endTime);

    @Query("SELECT e FROM Event AS e WHERE e.vehicle = :vehicle AND e.eventType = :eventType AND e.startTime = :startTime")
    public Event findByCompositeKey(@Param("vehicle") Vehicle vehicle,
                                @Param("eventType") EventType eventType,
                                @Param("startTime") long startTime);
}

1 个答案:

答案 0 :(得分:1)

安迪威尔金森的评论很有见。由于配置问题,问题是空事务管理器。