10
votes

Injection de dépendance avec printemps / junit / jpa

J'essaie de créer des tests Junit pour mes classes JPA DAO, à l'aide du ressort 2.5.6 et JUnit 4.8.1.

Mon cas de test ressemble à ceci: P>

SEVERE: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@fa60fa6] to prepare test instance [null(mil.navy.ndms.conops.common.dao.impl.MenuItem_Junit4_JPATest)]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mil.navy.ndms.conops.common.dao.impl.MenuItem_Junit4_JPATest': Injection of resource fields failed; nested exception is java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManagerFactory] is incompatible with resource type [javax.persistence.EntityManager]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:959)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:329)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:255)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:93)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:130)
    at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61)
    at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:54)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:52)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManagerFactory] is incompatible with resource type [javax.persistence.EntityManager]
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.checkResourceType(InjectionMetadata.java:159)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.(PersistenceAnnotationBeanPostProcessor.java:559)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$1.doWith(PersistenceAnnotationBeanPostProcessor.java:359)
    at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:492)
    at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:469)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:351)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:296)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:745)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:448)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    at java.security.AccessController.doPrivileged(AccessController.java:219)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:168)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:435)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:409)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:537)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
    at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:289)
    ... 18 more


0 commentaires

3 Réponses :


26
votes

Ce sont les combinaisons correctes d'annotation + interface: xxx

mais lors de l'utilisation de la transaction et de l'entité de printemps, vous n'avez pas besoin du entityManagerFactory du tout .

La raison pour laquelle vous n'avez pas besoin entitymanagerfactory est parce que la création du entitymanager est la responsabilité du gestionnaire de transactions. Voici ce qui se passe en bref:

  • Le gestionnaire de transactions est déclenché avant vos méthodes
  • Le gestionnaire de transactions obtient le entitymanagerfactory (il est injecté dedans), crée un nouveau entitymanager , définit dans un threadlocal et commence une nouvelle transaction.
  • alors il déléguette à la méthode de service
  • Chaque fois que @persisticcecontextextext est rencontré, un proxy est injecté (dans votre DAO), qui, chaque fois que vous avez accédé, obtient le entityManager qui a été défini dans le ThreadLocal

5 commentaires

Vous avez toujours besoin de l'entitémanager et de l'usine dans les DAOS, qui est le seul endroit où ils existent dans mon code.


Non, tu ne le fais pas. Par exemple, toute mon application n'a pas accès à l'usine que ce soit. L'entitémanager est injecté au printemps, donc pas besoin d'utiliser l'usine manuellement.


Droit. Nous faisons la même chose avec les DAOS (injectant l'entitémanager). J'injecte également l'usine (bien que je ne l'utilise pas actuellement pour quoi que ce soit). Il s'avère que tout le problème était une erreur de coupe simple et de pâte. J'utilisais @persisticcecontext sur l'entitéManagerFactory plutôt que sur @Persistenvie. Une fois que j'ai changé cela, ça a fonctionné ... merci pour le pointeur ...


@Steve - réponse acceptée avec 0 uppots semble étrange, alors je suggérerais que votre pratique étant le régulier - accepter + uppote


IMO Cette réponse n'est pas complète, car une configuration de printemps claire doit être fournie pour @persistencecontext Private EntityManager EntityManager; Exemple. Pourquoi regrouper l'entitémanager et l'entitémanagerfactory dans le même bloc lorsqu'ils ne devraient jamais apparaître dans la même classe ensemble.



0
votes

Je devais faire la combinaison ci-dessous, en dehors de l'ajout de bocal de printemps aux propriétés du projet-> Path d'aspect et permettant à des aspects de printemps dans les STS. Bonjour dans mon fichier de configuration contextuelle de mon application J'ai défini l'entitémanagerfactory.

@ContextConfiguration (emplacements = {"/meta-inf/spring/appllicationContext-domain.xml"}) La classe publique Readerest s'étend abstractjunit4springContextTestSts {

@persistCeConText EntityManager EntityManager;


0 commentaires

0
votes

J'ai aussi un même problème, quand j'ai ajouté le problème de l'API de Java-Persistence, a été résolu.

<dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>persistence-api</artifactId>
    <version>1.0.2</version>
</dependency>


0 commentaires