2

I spent a day trying to figure it out and eventually had to turn to stackoverflow for some expert advise.

I am setting up spring configuration using java to have two datasources and two LocalContainerEntityManagerFactoryBean as below. But Spring by default seems to look for entityManagerFactory() and throwing exception (included stacktrace below). How can I configure spring to use my entitymanagerfactories instead of default name.

@Bean(name="visionDataSource")
public DataSource visionDataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    // set properties..
    return dataSource;
}

@Bean(name="stormDataSource")
public DataSource visionDataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    // set properties..
    return dataSource;
}

  @Bean(name="visionentityManagerFactory")
public LocalContainerEntityManagerFactoryBean visionentityManagerFactory() {
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactoryBean.setDataSource(visionDataSource());
    //entityManagerFactoryBean.setPersistenceUnitManager(persistenceUnitManager());
    //entityManagerFactoryBean.setPersistenceXmlLocation(null);
    entityManagerFactoryBean.setPersistenceUnitName("visionEntityManagerFactory");
    entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);
    entityManagerFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
    entityManagerFactoryBean.setJpaProperties(hibProperties());
    entityManagerFactoryBean.afterPropertiesSet();
    System.out.println("*********************visionEntityManagerFactory********************");
    return entityManagerFactoryBean;
}

 @Bean(name="stormEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean stormEntityManagerFactory() {
    entityManagerFactoryBean.setDataSource(stormDataSource());
    // set other properties
    return entityManagerFactoryBean;
  }

Error LOG:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#1': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107) at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:616) at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:441) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1015) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:271) ... 51 more

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:549) at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1095) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:277) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323) ... 59 more

Update: I am using JPARepository

  public interface ContactRepository extends JpaRepository<Contact, Serializable> {
    List<Contact> findByCompanyId(int companyId);
  }

I already tried to extend a custom repository injecting entitymanager like below. But this did not help either.

  public interface ContactRepository extends DefaultRepository<Contact, Serializable> {
    List<Contact> findByCompanyId(int companyId);
   }

@NoRepositoryBean
public class DefaultRepositoryImpl<T, ID extends Serializable> extends SmpleJpaRepository<T, ID> implements 
                        DefaultRepository<T,ID> {

@PersistenceContext(unitName="visionEntityManagerFactory")
private EntityManager entityManager;

/**
 * @param domainClass
 * @param em
 */
 public DefaultRepositoryImpl(Class<T> domainClass, EntityManager em) {
 super(domainClass, em);
 }

 /**
  * {@inheritDoc}
  */
 protected Object getTargetRepository(RepositoryMetadata metadata) {
     return new DefaultRepositoryImpl<T, ID>((Class<T>) metadata.getDomainType(), entityManager);
 }
 /**
  * {@inheritDoc}
  */
 protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
     return DefaultRepository.class;
     }
  }
2
  • Can you post some code from one of your data access classes / repositories? The problem will be where one of those is attempting to inject entityManagerFactory instead of your alternatively-named beans. Commented Nov 7, 2013 at 22:55
  • I am using JPARepository. Added code snippet in my post. Commented Nov 7, 2013 at 23:10

1 Answer 1

1

One possible solution.

public class MyRepositoryImpl extends JdbcDaoSupport implements MyRepository {

    @Qualifier("odsDataSource")
    @Autowired(required = true)
    private DataSource ds;

    public MyRepositoryImpl() {
    }

    @PostConstruct
    void postConstruct() {
        setDataSource(ds);
    }

    ...
}

If you develop your repositories by extending JdbcDaoSupport (and also a few other Spring-provided helpers), then they will default to attempting to wire by name on the default "entityManagerFactory". So you need to initialise them by injecting your alternatively-named data beans.

Another possibility assuming you are using JPA.

@Repository
public class MyRepositoryImpl implements MyRepository {
    @PersistenceContext(unitName="MyPersistenceUnit")
    private EntityManager entityManager;

    public List<MyModel> findAll() {
        return entityManager.createNamedQuery("MyModel.findAll").getResultList();
    }
}

Update: For folks coming across this issue more recently, using Spring Boot and Spring Data JPA, I wrote a blog post running through the essentials of getting that working: http://scattercode.co.uk/2016/01/05/multiple-databases-with-spring-boot-and-spring-data-jpa/

Sign up to request clarification or add additional context in comments.

4 Comments

Can we have one custom repository and extend into all my repositories, so as to avoid writing implementation classes for all repositories. I added some code in my post to have custom repository. I am not sure if I am doing it correct way.
I'd say try using the @PersistenceContext annotation on your repository interface. I can't find any docs on it though, so I can't guarantee anything. :-/
Did you find the solution please? I'v exactly the same problem. Thank you.
I do now have a solution I could add, using Spring Data JPA if that's what you mean...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.