在我们的应用程序中,我们希望使用Spring和JPA设置多个数据源。因此我们创建了2个entityManagerFactory,2个数据源和2个事务管理器。
的web.xml
CREATE VIEW view_name AS
SELECT cast(column as integer) as column
FROM table;
的persistence.xml
<param-value>
/WEB-INF/a_spring.xml
/WEB-INF/b_spring.xml
</param-value>
a_spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="db1" transaction-type="RESOURCE_LOCAL">
<class>com.rh.domain.RcA</class>
</persistence-unit>
<persistence-unit name="db2" transaction-type="RESOURCE_LOCAL">
<class>com.rh.domain.Rcb</class>
</persistence-unit>
</persistence>
我还将另一个entityManagetFactory,Transaction Manager和dataSource声明为 b_spring.xml 。
错误
bean初始化失败;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 [javax.persistence.EntityManagerFactory]类型的唯一bean是 定义:预期单个bean但发现2引起: org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 [javax.persistence.EntityManagerFactory]类型的唯一bean是 定义:预期的单个bean,但发现2个 org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors(BeanFactoryUtils.java:303) 在 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:451) 在 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:428) 在 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:582) 在 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember.resolve(PersistenceAnnotationBeanPostProcessor.java:553) 在 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember.inject(PersistenceAnnotationBeanPostProcessor.java:489)
答案 0 :(得分:7)
如果有多个数据源配置,我们需要定义哪一个将被视为主数据源。我们可以指定在java配置中使用@Primary
注释或在XML bean配置中使用primary=true
。
由于在XML中创建了两个实体管理器,我们需要使用@Qualifier
来指定应该将哪个bean注入到哪里。在你的情况下,这样的事情。
@PersistenceContext(unitName = "db1")
public void setEntityManager(@Qualifier("entityManagerFactory") EntityManager entityMgr) {
this.em = entityMgr;
}
对于XML配置,我们可以做这样的事情
<bean id="BaseService" class="x.y.z.BaseService">
<property name="em" ref="entityManagerFactory"/>
<property name="em1" ref="entityManagerFactory1"/>
</bean>
<bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" parent="BaseService"/>
答案 1 :(得分:1)
您是否尝试提供包含EntityManagerFactory bean的包详细信息?
您可以在bean定义中提供包详细信息作为属性 -
<property name="packagesToScan" value="com.XX.XX.XX.XX" />
要在此块中添加的新属性 -
<bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="db2" />
<property name="dataSource" ref="dataSource1"/>
<-- add here for both beans -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
</bean>
</property>
</bean>
此外,您缺少persistenceXmlLocation
属性 -
<property name="persistenceXmlLocation" value="***/persistence.xml" />
答案 2 :(得分:1)
您发布的错误消息表明您为类型为EntityManagerFactory的对象按类型自动装配。到目前为止,您所显示的代码都没有包含这样的注入,这意味着它可能在您尚未发布的某些代码中。
如果您要发布错误的完整堆栈跟踪,您将能够向上移动堆栈以查看哪个bean包含对EntityManagerFactory对象的不可满足的引用,这反过来会让您更改引用它以允许引用您想要的特定bean。
<强>更新强>
根据您提供的更多信息(谢谢)和一些Google搜索,似乎其他用户同样发现指定unitName不足以获得正确的EntityManager注入。几篇帖子在线备份@ lucid建议使用@Qualifier注释让Spring选择正确的bean,但遗憾的是that annotation was introduced in 2.5所以只有你升级才能使用它。 (考虑到你正在使用的Spring框架的年龄,这可能是一个好主意,但这是一个单独的对话。)
但是,several users have indicated在2.0.5中可以使用备用方法,使用引用多个数据源的单个PersistenceUnitManager而不是每个引用单个数据源的多个持久性单元。来自官方的Spring文档:https://docs.spring.io/spring/docs/2.0.x/reference/orm.html#orm-jpa-multiple-pu。
总的来说,我建议您考虑升级到不超过十年的Spring版本,这样可以让您根据@ lucid的答案指定@Qualifier注释。但是如果由于某种原因这是不可能的,那么PersistenceUnitManager方法应该会让你有办法让它在Spring 2.0.5中运行。
答案 3 :(得分:0)
有些事情对我来说并不好看。 setter的名称与属性名称不匹配,我认为这很重要,第二件事是关于继承,有些注释有时只适用于不在基类中的具体类。我会尝试更改基本服务,如下所示。
public class BaseService {
@PersistenceContext(unitName = "db2")
private EntityManager em;
@PersistenceContext(unitName = "db1")
private EntityManager em1;
public EntityManager getEm() {
return em;
}
protected EntityManager getEm2() {
return em1;
}
public void setEm(EntityManager entityMgr) {
this.em = entityMgr;
}
public void setEm1(EntityManager entityMgr) {
this.em = entityMgr;
}
}
如果这不起作用,我可能会尝试删除基类,看看我是否将注释放在我可以使用的具体类之下,我会这样做只是将注释移动到RcAbcMaintenanceServiceImpl
类和删除从BaseService继承的extend语句
另外,我注意到PersistenceContext
注释有另一个参数https://docs.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html,因此您可以尝试使用该名称来匹配bean定义中的id。