Spring, JPA, Hibernate, Tomcat: kann Nicht finden, Persistenz-Einheit beim laden von Spring application context
Ich habe eine Anwendung Kontext, wo ich bin versucht, setup-JPA:
application-context.xml:
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="persistenceUnits">
<map>
<entry key="pu1" value="pu1" />
<entry key="pu2" value="pu2" />
</map>
</property>
<property name="defaultPersistenceUnitName" value="pu1" />
</bean>
<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
<property name="persistenceUnitName" value="pu1" />
<property name="dataSource" ref="dataSource1" />
</bean>
<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.SQLServer2005Dialect" />
</bean>
</property>
<property name="persistenceUnitName" value="pu2" />
<property name="dataSource" ref="dataSource2" />
</bean>
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven />
<bean id="transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf1" />
<property name="dataSource" ref="dataSource1" />
</bean>
<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf2" />
<property name="dataSource" ref="dataSource2" />
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config/db/database.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
</bean>
<!-- The actual config of the database is read from the properties file database.properties -->
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"
p:acquireIncrement="5" p:idleConnectionTestPeriod="14400" p:maxPoolSize="50" p:maxStatements="15"
p:minPoolSize="5" p:testConnectionOnCheckout="true" p:preferredTestQuery="SELECT 4;"
p:driverClass="${db.system1.driver}" p:jdbcUrl="${db.system1.url}" p:user="${db.system1.user}" p:password="${db.system1.password}" />
<bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" p:acquireIncrement="5" p:idleConnectionTestPeriod="60" p:maxPoolSize="10"
p:maxStatements="50" p:minPoolSize="3" p:testConnectionOnCheckout="true" p:preferredTestQuery="SELECT 4;"
p:driverClass="${db.system2.driver}" p:jdbcUrl="${db.system2.url}" p:user="${db.system2.user}" p:password="${db.system2.password}" />
<context:annotation-config />
<context:component-scan base-package="com.myapp.model.manager"/>
persistence.xml:
<persistence-unit name="pu1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.myapp.model.Address</class>
<class>com.myapp.model.AgressoFile</class>
<class>com.myapp.model.CustomerGroup</class>
...
</persistence-unit>
<persistence-unit name="pu2" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.myapp.model.CompetenceArea</class>
<class>com.myapp.model.CompetenceAreaCategory</class>
...
</persistence-unit>
Ich bin laden Anwendungskontext in einer web.xml diese Weise:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/application-context.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
CompetenceAreaManager Klasse, der sucht, in dem die gescannten Paket "com.myapp.Modell.manager" hat folgende Inhalte:
@Service
public class CompetenceAreaManager {
@PersistenceUnit(unitName = "pu2")
private EntityManagerFactory entityManagerFactory;
@SuppressWarnings("unchecked")
public List<CompetenceArea> getCompetenceAreas() {
List<CompetenceArea> competenceAreaList = null;
EntityManager em = entityManagerFactory.createEntityManager();
Query q = em.createNamedQuery(CompetenceArea.FIND_ALL);
competenceAreaList = q.getResultList();
return competenceAreaList;
}
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}
Jedoch, wenn ich versuche, führen Sie die Anwendung, die in Tomcat 7.0, bekomme ich die folgende Fehlermeldung:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'competenceAreaManager': Injection of persistence dependencies failed; nested exception is java.lang.IllegalStateException: Could not obtain EntityManagerFactory [pu2] from JNDI
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:343)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1122)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
...
Caused by: java.lang.IllegalStateException: Could not obtain EntityManagerFactory [pu2] from JNDI
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.getPersistenceUnit(PersistenceAnnotationBeanPostProcessor.java:435)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:643)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:637)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
...
Caused by: javax.naming.NameNotFoundException: Name [pu2] is not bound in this Context. Unable to find [pu2].
at org.apache.naming.NamingContext.lookup(NamingContext.java:820)
at org.apache.naming.NamingContext.lookup(NamingContext.java:168)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:158)
at javax.naming.InitialContext.lookup(Unknown Source)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
...
Irgendeine Idee, was ich falsch mache?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie die PersistenceAnnotationBeanPostProcessor mit persistenceUnits, Sie informieren die PersistenceAnnotationBeanPostProcessor, dass Eiter kommen von JNDI (wie in der javadoc für setPersistenceUnits () - Methoden erwähnt). Der stack-trace zeigt eigentlich die fehlerhafte JNDI-lookup.
Da Sie über
<context:annotation-config/>
im application-context.xml Sie brauchen nicht zu erklären, PersistenceAnnotationBeanPostProcessor, da wird man automatisch registriert werden, das sieht Eiter durch das Lesen Ihrer META-INF/persistence.xml Dateien in den classpath, das ist eigentlich das, was Sie erwarten.Ihre Konfiguration sollte so einfach wie diese :
persistence.xml bleibt unverändert
CompetenceAreaManager
Als Sergey Makarov erwähnt, nur inject EntityManager mit @PersistenceContext anstatt des Einspritzens von EntityManagerFactory mit @PersistenceUnit. Die em ist transaktional (also gebunden an den thread, damit die Gewährleistung der thread-Sicherheit für Ihr DAO), und man kann noch konfigurieren, @PersistenceContext mit unitName zur Festlegung der PU die EM hat gebunden werden.
application-context.xml
Einfach die Erklärung der PersistenceAnnotationBeanPostProcessor bean. Der rest der Datei bleibt unverändert.
Ich habe nicht versucht, Ihre bestimmten config (2 PUs), aber die Konfiguration, die ich erwähnen möchte, ist der, den ich immer benutze, mit Erfolg.
So weit ich verstanden habe, von meinem letzten Erlebnis einrichten 2 EntityManagerFactory in der gleichen Anwendung - @PersistenceUnit(unitName="myPU") einfach überhaupt nicht funktioniert.
Ich würde vorschlagen, inject EntityManager, nicht EntityManagerFactory. Das ist klar, da Sie immer wissen, welches von EMF verwendet wird. Gleiche für die Angabe rechts TransactionManager.
Aktualisierten code von der service-Klasse:
Solche Injektion ist sicher seit dem Frühjahr injiziert einen proxy EntityManager, die garantiert thread-Sicherheit.
<context:annotation-config /> <context:component-scan base-package="com.myapp.model.manager"/>
. Die Sache ist, dass ich möchte, um Sie in den Anwendungskontext.