Search code examples
jpaspring-bootmultiple-databases

multiple datasource with spring boot jpa


Trying to setup dual datasource with spring boot, but it would seem alot harder then first thought,

tried to follow tons of tutorials and guides, but keep getting error with my repos.

application properties

# Primary DataSource
datasource.primary.url=url
datasource.primary.username=user
datasource.primary.password=pw
datasource.primary.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

# Secondary DataSource
datasource.secondary.url=url
datasource.secondary.username=user
datasource.secondary.password=pw
datasource.secondary.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

# hibernate strategy (create/update)
spring.jpa.hibernate.ddl-auto=update

# name strategy
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

first db config

    package com.anders.cphbusiness.db;

    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;

    import javax.persistence.EntityManagerFactory;
    import javax.persistence.PersistenceContext;
    import javax.sql.DataSource;

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            basePackages = {"com.anders.cphbusiness.repositories"},
            entityManagerFactoryRef = "primaryEM")

    public class LoadDataSourceConfig {
        @Bean(name = "primaryDS")
        @Primary
        @ConfigurationProperties(prefix = "datasource.primary")
        public DataSource loadingDataSource() {
            return DataSourceBuilder.create().build();
        }

        @PersistenceContext(unitName = "primaryPU")
        @Primary
        @Bean(name = "primaryEM")
        public LocalContainerEntityManagerFactoryBean loadingEntityManagerFactory(
                EntityManagerFactoryBuilder builder, @Qualifier("primaryDS") DataSource primaryDS) {
            return builder
                    .dataSource(primaryDS)
                    .persistenceUnit("primaryPU")
                    .packages("com.anders.cphbusiness.entitiesModel")
                    .build();
        }

        @Primary
        @Bean(name = "primaryTM")
        public PlatformTransactionManager transactionManager(
                @Qualifier("primaryEM") EntityManagerFactory entityManagerFactory) {
            return new JpaTransactionManager(entityManagerFactory);
        }

    }

second db config

package com.anders.cphbusiness.db;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = "com.anders.cphbusiness.secondRepo",
        entityManagerFactoryRef = "secondaryEM",
        transactionManagerRef = "secondaryTransactionManager")

public class StoreDataSourceConfig {

    @Bean(name = "secondaryDS")
    @ConfigurationProperties(prefix = "datasource.secondary")
    public DataSource storingDataSource() {
        return DataSourceBuilder.create().build();
    }

    @PersistenceContext(unitName = "secondaryPU")
    @Bean(name = "secondaryEM")
    public LocalContainerEntityManagerFactoryBean storingEntityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("secondaryDS") DataSource secondaryDS) {
        return builder
                .dataSource(secondaryDS)
                .packages("com.anders.cphbusiness.storingModel")
                .persistenceUnit("secondaryPU")
                .build();
    }

    @Bean(name = "secondaryTM")
    public PlatformTransactionManager secondaryTransactionManager(
            @Qualifier("secondaryEM") EntityManagerFactory secondaryEM) {
        return new JpaTransactionManager(secondaryEM);
    }
}

repo examples

package com.anders.cphbusiness.repositories;

import com.anders.cphbusiness.entitiesModel.WagerBoard;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import javax.persistence.PersistenceContext;

@Repository
@PersistenceContext(name = "primaryEM")
public interface WagerBoardRepo extends JpaRepository<WagerBoard, String> {

}

storeDbEntRepo:

package com.anders.cphbusiness.secondRepo;

import com.anders.cphbusiness.entitiesModel.WagerBoard;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import javax.persistence.PersistenceContext;

@Repository
@PersistenceContext(name = "secondaryEM")
public interface StoreDbEntRepo extends JpaRepository<WagerBoard, String> {

}

the error

2017-02-07 10:57:54.222 ERROR 7176 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'storeDbEntRepo': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.anders.cphbusiness.entitiesModel.WagerBoard
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:742) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at com.anders.cphbusiness.DsRngCheckerApplication.main(DsRngCheckerApplication.java:18) [main/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.anders.cphbusiness.entitiesModel.WagerBoard
    at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:210) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:70) ~[spring-data-jpa-1.11.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:67) ~[spring-data-jpa-1.11.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:152) ~[spring-data-jpa-1.11.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:99) ~[spring-data-jpa-1.11.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:81) ~[spring-data-jpa-1.11.0.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:199) ~[spring-data-commons-1.13.0.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277) ~[spring-data-commons-1.13.0.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263) ~[spring-data-commons-1.13.0.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:101) ~[spring-data-jpa-1.11.0.RELEASE.jar:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 21 common frames omitted

Solution

  • Your main problem is: not a managed type: class com.anders.cphbusiness.entitiesModel.WagerBoard

    Your StoreDbEntRepo is using "secondaryEM", but is using WagerBoard entity to create the repo.

    WagerBoard entity belongs to entitiesModel package. If you want to use that entity into your StoreDbEntRepo, your need to scan the proper package in your EntityManager, doing an update from

    .packages("com.anders.cphbusiness.storingModel")
    

    to

    .packages("com.anders.cphbusiness.storingModel","com.anders.cphbusiness.entitiesModel").
    

    But if your don't, use an entity that belongs to storingModel package to create the StoreDbEntRepo.