I've a class EntityLoader that's used to fetch some data from a MySQL database using Hibernate. But now the need is to fetch data from two different databases (MySQL and Oracle in this case). So I want to have two beans of EntityLoader but injecting a different SessionFactory in each one.
EntityLoader is defined as follows:
package com.demo
@Component
public class EntityLoader {
@Autowired
private SessionFactory sessionFactory;
/* Code ... */
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
And the context configuration is:
<context:component-scan base-package="com.demo" />
<bean id="mysqlSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
So far it works fine. Over this I have done the following changes:
- Exclude
EntityLoaderfromcomponent-scanin order to avoid the auto creation of a EntityLoader - Add
mysqlSessionFactoryandoracleSessionFactorybean definitions - Add
mysqlEntityRepoLoaderandoracleEntityRepoLoaderbean definitions
Note that in mysqlEntityRepoLoader and oracleEntityRepoLoader I've added the attribute autowired="no" hoping that this would
tell Spring to not autowire the SessionFactory and use the defined ref instead.
The resulting configuration is:
<context:component-scan base-package="com.demo">
<context:exclude-filter type="regex" expression="com.demo.EntityLoader"/>
</context:component-scan>
<bean id="mysqlSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- ... config ... -->
</bean>
<bean id="oracleSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- ... config ... -->
</bean>
<bean id="mysqlEntityRepoLoader" class="com.dome.imserso.api.core.data.EntityRepoLoader" autowire="no">
<property name="sessionFactory" ref="mysqlSessionFactory"/>
</bean>
<bean id="oracleEntityRepoLoader" class="com.dome.imserso.api.core.data.EntityRepoLoader" autowire="no">
<property name="sessionFactory" ref="oracleSessionFactory"/>
</bean>
But it seems that Spring is trying first to autowire the SessionFactory in any case. I get the following error:
No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: mysqlSessionFactory,oracleSessionFactory
If I remove the @Autowired all works fine. But I would like to maintain it, as this code is part of a generic lib used for other apps where the usual case is to load only from one database.
Is there any way to accomplish it without removing the annotation?
If you are able to modify your lib which contains EntityLoader, following these 2 step will do the trip :
In
EntityLoadermake your@Autowiredoptional:@Autowired(required=false)
In XML configuration, exclude mysqlSessionFactory and oracleSessionFactory beans from autowire candidates, add
autowire-candidate="false"to each sessionFactory:Voilà!