本文介绍了使用JUnit 4和Spring Data进行Spring测试JPA:NoSuchMethodError org.hibernate.engine.spi.SessionFactoryImplementor.getProperties的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用> SpringJUnit4ClassRunner ,JUnit 4和Spring Test为 Service 写了单元测试,它使用Spring Data JPA Repository 和嵌入的HSQL数据库:

  @Ignore 
@RunWith SpringBUnit4ClassRunner.class)
@ContextConfiguration(classpath *:unitTestFullConfig.xml)
public class InMemoryDBFullTestBaseClass {
}

public final class ActorServiceImplTest extends InMemoryDBFullTestBaseClass {
@Inject
私人ActorService服务;

@Test
public final void saveActor()throws Exception {
service.save(new ActorDTO(null,testName,testSurname,new Date(),Collections .emptyList()));

assertEquals(1,service.getAll()。size());






我运行,并带有config:

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xmlns:jpa =http://www.springframework.org/schema/data/jpa
xmlns:tx =http://www.springframework.org/schema/tx
xmlns:jdbc =http://www.springframework.org/schema/jdbcxmlns:mvc =http://www.springframework.org/schema/mvc
xmlns:context =http:
xsi:schemaLocation =http://www.springframework.org/schema/beans
http://www.springframework.org/schema/ beans / spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa- 1.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd

http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springfram ework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema /context/spring-context.xsd\">

< jdbc:embedded-database id =dataSourcetype =HSQL>
< / jdbc:embedded-database>
< tx:annotation-driven />
< mvc:annotation-driven />
< context:component-scan base-package =beans/>

< bean id =hibernateJpaVendorAdapter
class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter/>

< bean id =entityManagerFactory
class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =dataSourceref =dataSource/>
< property name =jpaVendorAdapterref =hibernateJpaVendorAdapter/>
< property name =loadTimeWeaver>
< bean class =org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver/>
< / property>
< property name =jpaProperties>
<道具>
< prop key =hibernate.dialect> org.hibernate.dialect.HSQLDialect< / prop>
< prop key =javax.persistence.schema-generation.database.action> none< / prop>
< prop key =hibernate.ejb.use_class_enhancer> true< / prop>
< prop key =hibernate.hbm2ddl.auto>建立< / prop>
< prop key =hibernate.show_sql> true< / prop>
< /道具>
< / property>
<! - 设置实体的基本包 - >
< property name =packagesToScanvalue =models/>
< property name =sharedCacheModevalue =ENABLE_SELECTIVE/>
< property name =validationModevalue =NONE/>
< property name =persistenceUnitNamevalue =testJPA/>
< / bean>

< bean id =transactionManager
class =org.springframework.orm.jpa.JpaTransactionManager>
< property name =entityManagerFactoryref =entityManagerFactory/>
< / bean>



配置Spring Data JPA并设置
库接口的基础包
- >
< jpa:repositories base-package =beans.repositories/>
< / beans>

但是我得到了:

测试配置和 applicationContext.xml (它适用于Tomcat应用程序)是用于测试的嵌入式数据库,但即使我使用 dataSource 来自项目:

 < bean id =dataSourceclass =com.mchange.v2.c3p0.ComboPooledDataSourcedestroy-方法= 关闭 > 
< property name =driverClassvalue =org.postgresql.Driver/>
< property name =jdbcUrlvalue =jdbc:postgresql:// localhost:5432 / film-site/>
< property name =uservalue =postgres/>
< property name =passwordvalue =postgres/>
< property name =maxPoolSizevalue =10/>
< property name =maxStatementsvalue =0/>
< property name =minPoolSizevalue =5/>
< / bean>

我仍然面临同样的问题(项目正常工作)。另外,我不认为问题在于我没有 hibernate.properties 文件,因为我在这里询问了它:。我使用 Spring 4.3.2.RELEASE ,使用 Hibernate Core 5.2.0.Final , Hibernate Entity Manager 5.1.0.Final , Spring Data 1.10.2.RELEASE JPA , Spring Data Commons 1.12.2 .RELEASE 和 Spring Data Commons Core 1.4.1.RELEASE 。如果有人能帮助我,我会很高兴 - 事先感谢您。
更新:对于 jpaProperties 更改为 jpaPropertyMap > entityManagerFactory :

 < property name =jpaPropertyMap> 
< map>
< entry key =hibernate.dialectvalue =org.hibernate.dialect.HSQLDialect/>
< entry key =javax.persistence.schema-generation.database.actionvalue =none/>
< entry key =hibernate.ejb.use_class_enhancervalue =true/>
< entry key =hibernate.hbm2ddl.autovalue =create/>
< entry key =hibernate.show_sqlvalue =true/>
< / map>
< / property>

注释依赖于 hibernate-entitymanager ,但它仍然不起作用。当我切换到Hibernate 5.1
UPDATE 2时,我也遇到同样的问题:我创建了一个Java配置版本,可能会帮助别人查看我犯了什么错误:

  package config; 

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

import javax.persistence.EntityManagerFactory;
import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class HibernateConfig {
@Bean
public DataSource dataSource(){
return new EmbeddedDatabaseBuilder()。setType(EmbeddedDatabaseType.HSQL) 。建立();

$ b $ //创建Hibernate的默认配置
@Bean
public JpaVendorAdapter jpaVendorAdapter(){
return new HibernateJpaVendorAdapter();


//配置实体管理器的工厂bean
@Bean $ b $ publicContainerEntityManagerFactoryBean();

factory.setDataSource(dataSource());
factory.setJpaVendorAdapter(jpaVendorAdapter());
factory.setLoadTimeWeaver(新InstrumentationLoadTimeWeaver());
factory.setJpaPropertyMap(createJpaProperties());
factory.setPackagesToScan(models);
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setPersistenceUnitName(testJPA);

退货工厂;


$Be
public JpaTransactionManager transactionManager(){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory((EntityManagerFactory)entityManagerFactory());
返回transactionManager;
}

私人地图< String,?> createJpaProperties(){
Map< String,Object> propertyMap = new HashMap();
propertyMap.put(hibernate.dialect,org.hibernate.dialect.HSQLDialect);
propertyMap.put(javax.persistence.schema-generation.database.action,none);
propertyMap.put(hibernate.ejb.use_class_enhancer,true);
propertyMap.put(hibernate.hbm2ddl.auto,create);
propertyMap.put(hibernate.show_sql,true);

返回propertyMap;
}
}

更新2016-10-04 strong>:我创建了 Github存储库显示问题,那么你会看到这个应用程序本身工作得很好(只需在 index,jsp 文件中的内添加 Actor 但它不适用于测试)。附:我从Intellij IDEA(运行按钮)部署 war:爆炸到Tomcat 8.0.24本地实例。

解决方案

我在GitHub上检查了您的示例,并且在测试代码修改后,Unit-Test已经为我工作。但首先我想说的是,在开始的时候,这对我来说有点像另一个例外。它如下所示:

 原因:java.lang.ClassCastException:org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean $$ EnhancerBySpringCGLIB $$ fedd095f不能转换为javax.persistence.EntityManagerFactory 

JpaTransactionManager HibernateConfig 中的code>配置需要更改以解决此问题,如下所示:

  @Bean 
public JpaTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
返回transactionManager;



$ b

与原始配置版本不同,在这种情况下 EntityManagerFactory 注入为Spring托管bean,而不是使用 HibernateConfig.entityManagerFactory()方法创建的独立实例。



还做了其他更改,但它们与Question主题没有直接关系。如果您愿意,我也可以提供。


With SpringJUnit4ClassRunner, JUnit 4 and Spring Test I wrote unit test for Service which uses Spring Data JPA Repository and embedded HSQL database:

@Ignore
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:unitTestFullConfig.xml")
public class InMemoryDBFullTestBaseClass {
}

public final class ActorServiceImplTest extends InMemoryDBFullTestBaseClass {
   @Inject
    private ActorService service;

    @Test
    public final void saveActor () throws Exception {
        service.save(new ActorDTO(null, "testName", "testSurname", new Date(), Collections.emptyList()));

        assertEquals(1, service.getAll().size());
    }
}

I run test with required javaagent option on VM, with config:

<?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:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd

       http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Configure the data source bean -->
    <jdbc:embedded-database id="dataSource" type="HSQL">
    </jdbc:embedded-database>
    <!-- Enable annotation driven transaction management -->
    <tx:annotation-driven/>
    <mvc:annotation-driven/>
    <context:component-scan base-package="beans"/>

    <!-- Create default configuration for Hibernate -->
    <bean id="hibernateJpaVendorAdapter"
          class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>

    <!-- Configure the entity manager factory bean -->
    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
        </property>
        <!-- Set JPA properties -->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                <prop key="javax.persistence.schema-generation.database.action">none</prop>
                <prop key="hibernate.ejb.use_class_enhancer">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
        <!-- Set base package of your entities -->
        <property name="packagesToScan" value="models"/>
        <!-- Set share cache mode -->
        <property name="sharedCacheMode" value="ENABLE_SELECTIVE"/>
        <!-- Set validation mode -->
        <property name="validationMode" value="NONE"/>
        <property name="persistenceUnitName" value="testJPA" />
    </bean>

    <!-- Configure the transaction manager bean -->
    <bean id="transactionManager"
          class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>



    <!--
      Configure Spring Data JPA and set the base package of the
      repository interfaces
    -->
    <jpa:repositories base-package="beans.repositories"/>
</beans>

But I got:

The only difference between test config and applicationContext.xml (which works for Tomcat app) is embedded database used in test, but even if I use dataSource from project:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="org.postgresql.Driver"/>
    <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/film-site"/>
    <property name="user" value="postgres"/>
    <property name="password" value="postgres"/>
    <property name="maxPoolSize" value="10"/>
    <property name="maxStatements" value="0"/>
    <property name="minPoolSize" value="5"/>
</bean>

I still face the same issue (project works normally). Also, i don't think problem is that I don't have hibernate.properties file, cause I asked about it here: Spring Data configuration - hibernate.properties not found. I use Spring 4.3.2.RELEASE, with Hibernate Core 5.2.0.Final, Hibernate Entity Manager 5.1.0.Final, Spring Data 1.10.2.RELEASE JPA, Spring Data Commons 1.12.2.RELEASE and Spring Data Commons Core 1.4.1.RELEASE. I will be happy if anybody would help me - thank you in advance.UPDATE: I changed jpaProperties to jpaPropertyMap for entityManagerFactory:

<property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
            <entry key="javax.persistence.schema-generation.database.action" value="none" />
            <entry key="hibernate.ejb.use_class_enhancer" value="true" />
            <entry key="hibernate.hbm2ddl.auto" value="create" />
            <entry key="hibernate.show_sql" value="true" />
        </map>
    </property>

And comment dependency for hibernate-entitymanager, but it still does not work. Also I have the same issue when I switch to Hibernate 5.1UPDATE 2: I created a Java config version, maybe it will help someone to see where I made a mistake:

package config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

import javax.persistence.EntityManagerFactory;
import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class HibernateConfig {
    @Bean
    public DataSource dataSource () {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build();
    }

//    Create default configuration for Hibernate
    @Bean
    public JpaVendorAdapter jpaVendorAdapter () {
        return new HibernateJpaVendorAdapter();
    }

//    Configure the entity manager factory bean
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory () {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

        factory.setDataSource(dataSource());
        factory.setJpaVendorAdapter(jpaVendorAdapter());
        factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
        factory.setJpaPropertyMap(createJpaProperties());
        factory.setPackagesToScan("models");
        factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
        factory.setValidationMode(ValidationMode.NONE);
        factory.setPersistenceUnitName("testJPA");

        return factory;
    }

    @Bean
    public JpaTransactionManager transactionManager () {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory((EntityManagerFactory) entityManagerFactory());
        return transactionManager;
    }

    private Map<String, ?> createJpaProperties () {
        Map<String, Object> propertyMap = new HashMap();
        propertyMap.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        propertyMap.put("javax.persistence.schema-generation.database.action", "none");
        propertyMap.put("hibernate.ejb.use_class_enhancer", true);
        propertyMap.put("hibernate.hbm2ddl.auto", "create");
        propertyMap.put("hibernate.show_sql", true);

        return propertyMap;
    }
}

UPDATE 2016-10-04: I created Github repository which shows problem, there you will see that app itself works quite well (just add Actor in form inside index,jsp file, but it does not work for test). P.S. I deploy war:exploded to Tomcat 8.0.24 local instance from Intellij IDEA ("Run" button).

解决方案

I checked your example on GitHub, and Unit-Test has worked for me after some code modifications. But first I wanted to say that it was little bit another Exception for me in the beginning. It was like follows:

Caused by: java.lang.ClassCastException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean$$EnhancerBySpringCGLIB$$fedd095f cannot be cast to javax.persistence.EntityManagerFactory

JpaTransactionManager configuration in HibernateConfig need to be changed to fix this problem like follows:

@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);
    return transactionManager;
}

Unlike the original config version in this case EntityManagerFactory is injected as Spring managed bean, instead of separate instance that created with HibernateConfig.entityManagerFactory() method.

Also other changes have been made, but they are not directly related to the Question subject. I can provide them too if you want.

这篇关于使用JUnit 4和Spring Data进行Spring测试JPA:NoSuchMethodError org.hibernate.engine.spi.SessionFactoryImplementor.getProperties的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 20:38
查看更多