Using two EntityManagerFactory within one spring boot app

Viewed 1212

I am trying to configure two EntityManagerFactory for one spring boot application. Each of those EntityManagerFactorys should work with different databases. Also would be great if one of them would be used as a default (e.g. when not explicit information was provided during on which one should be used).

Here is my code:

pkg/Application.java

package pkg;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).run(args);
    }
}

pkg/PrimaryDbConfig.java

package pkg;

import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
public class PrimaryDbConfig {
    public static final String DB = "primary";

    @Bean
    @Primary
    public DataSource primaryDataSource() {
        JdbcDataSource ds = new JdbcDataSource();
        ds.setURL("jdbc:h2:file:~\\db\\test;AUTO_SERVER=TRUE");
        ds.setUser("sa");
        ds.setPassword("sa");
        return ds;
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactoryBean() {

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setPersistenceUnitName(DB);
        factoryBean.setDataSource(primaryDataSource());
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.setPackagesToScan("pkg.entities");
        return factoryBean;
    }

    @Bean
    @Primary
    public PlatformTransactionManager primaryTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(primaryEntityManagerFactoryBean().getObject());
        return transactionManager;
    }
}

pkg/SecondaryDbConfig.java

package pkg;

import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
public class SecondaryDbConfig {
    public static final String DB = "secondary";

    @Bean
    public DataSource secondaryDataSource() {
        JdbcDataSource ds = new JdbcDataSource();
        ds.setURL("jdbc:h2:file:~\\db\\test2;AUTO_SERVER=TRUE");
        ds.setUser("sa");
        ds.setPassword("sa");
        return ds;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactoryBean() {

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setPersistenceUnitName(DB);
        factoryBean.setDataSource(secondaryDataSource());
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.setPackagesToScan("pkg.entities");
        return factoryBean;
    }

    @Bean
    public PlatformTransactionManager secondaryTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(secondaryEntityManagerFactoryBean().getObject());
        return transactionManager;
    }
}

pkg/repositories/PrimaryRepository.java

package pkg.repositories;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;

import javax.persistence.EntityManager;

@Repository
@Transactional
public class PrimaryRepository {
    private final EntityManager entityManager;

    public PrimaryRepository(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public SomeEntity find(Integer id) {
        return entityManager.find(SomeEntity.class, id);
    }
}

pkg/repositories/SecondaryRepository.java

package pkg.repositories;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Repository
@Transactional("secondaryTransactionManager")
public class SecondaryRepository {
    @PersistenceContext(unitName = "secondary")
    private final EntityManager entityManager;

    public SecondaryRepository(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public SomeEntity find(Integer id) {
        return entityManager.find(SomeEntity.class, id);
    }
}

build.gradle

plugins {
    id 'org.springframework.boot' version '1.5.7.RELEASE'
}

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile "com.h2database:h2:1.4.193"
    compile "org.hibernate:hibernate-core:5.2.10.Final"
    compile ("org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE") {
        exclude module: 'tomcat-jdbc'
    }
}

Running this app I am getting next error:

Description:

Parameter 0 of constructor in pkg.repositories.PrimaryRepository required a single bean, but 2 were found:
    - org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
    - org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null
0 Answers
Related