Java Spring、JPA、Hibernate、Tomcat:加载Spring应用程序上下文时找不到持久化单元
我有一个试图设置JPA的应用程序上下文: 应用程序上下文.xml:Java Spring、JPA、Hibernate、Tomcat:加载Spring应用程序上下文时找不到持久化单元,java,spring,hibernate,jpa,tomcat7,Java,Spring,Hibernate,Jpa,Tomcat7,我有一个试图设置JPA的应用程序上下文: 应用程序上下文.xml: <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"> <property name="persistenceUnits"> <map> <entry key="pu1" value="pu1" />
<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-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>
知道我做错了什么吗?据我最近在同一个应用程序中设置2个EntityManager工厂的期限所知,@PersistenceUnit(unitName=“myPU”)根本不起作用 我建议注射EntityManager,而不是EntityManager工厂。这是很清楚的,因为您总是知道使用哪种EMF。指定正确的TransactionManager时也是如此 服务类别的更新代码:
@Service
public class CompetenceAreaManager
{
@PersistenceContext(unitName = "emf1")
private EntityManager em;
@SuppressWarnings("unchecked")
@Transactional(transactionManager="transactionManager1", readOnly=true)
public List<CompetenceArea> getCompetenceAreas()
{
List<CompetenceArea> competenceAreaList = null;
Query q = em.createNamedQuery(CompetenceArea.FIND_ALL);
competenceAreaList = q.getResultList();
return competenceAreaList;
}
}
@服务
公共类能力领域经理
{
@PersistenceContext(unitName=“emf1”)
私人实体管理者;
@抑制警告(“未选中”)
@事务性(transactionManager=“transactionManager1”,只读=true)
公共列表GetCompetencyAreas()
{
列表能力AreaList=null;
Query q=em.createNamedQuery(competincearea.FIND_ALL);
CompetencyAreaList=q.getResultList();
返回能力范围列表;
}
}
这种注入是安全的,因为Spring注入了EntityManager的代理,从而保证了线程安全 如果将PersistenceAnnotationBeanPostProcessor配置为persistenceUnits,则会通知PersistenceAnnotationBeanPostProcessor PU来自JNDI(正如setPersistenceUnits()方法的javadoc所提到的)。堆栈跟踪实际上显示了失败的JNDI查找 由于您在application-context.xml中使用
,因此不需要声明PersistenceAnnotationBeanPostProcessor,因为一个将自动注册,它通过读取位于类路径中的META-INF/persistence.xml文件来查找PUs,这实际上是您所期望的
您的配置应该如下所示:
persistence.xml保持不变
能力区域经理
正如Sergey Makarov提到的,只需将EntityManager注入@PersistenceContext,而不是将EntityManager工厂注入@PersistenceUnit。em是事务性的(因此绑定到线程,从而确保DAO的线程安全),您仍然可以使用unitName配置@PersistenceContext,以便指定em必须绑定到的PU
应用程序上下文.xml
只需删除PersistenceAnnotationBeanPostProcessorbean的声明。文件的其余部分保持不变
我还没有尝试过您的特定配置(2个PUs),但我提到的配置是我一直使用的配置,并取得了成功。谢谢您的回复!如果我将这些行从应用程序上下文移动到DispatherServlet的servlet上下文中,我的设置就会起作用:
。问题是我想把它们保存在应用程序上下文中。我想你需要用DispatcherServlet配置的描述更新你的帖子。嗯。。。坦率地说,我将DispatherServlet添加到应用程序中只是为了测试,以便了解如果将“组件扫描”移动到其上下文中会发生什么。它实际上与我发布的问题无关,因此我可能不会在这里发布配置,以免混淆读者。非常感谢您的回答和详细解释!它就像一个符咒
@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;
}
}
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)
...
@Service
public class CompetenceAreaManager
{
@PersistenceContext(unitName = "emf1")
private EntityManager em;
@SuppressWarnings("unchecked")
@Transactional(transactionManager="transactionManager1", readOnly=true)
public List<CompetenceArea> getCompetenceAreas()
{
List<CompetenceArea> competenceAreaList = null;
Query q = em.createNamedQuery(CompetenceArea.FIND_ALL);
competenceAreaList = q.getResultList();
return competenceAreaList;
}
}