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
EntityLoader
fromcomponent-scan
in order to avoid the auto creation of a EntityLoader - Add
mysqlSessionFactory
andoracleSessionFactory
bean definitions - Add
mysqlEntityRepoLoader
andoracleEntityRepoLoader
bean 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
EntityLoader
make your@Autowired
optional:@Autowired(required=false)
In XML configuration, exclude mysqlSessionFactory and oracleSessionFactory beans from autowire candidates, add
autowire-candidate="false"
to each sessionFactory:Voilà!