Search code examples
spring-data-jpaspring-data

Entity Autocreation not working after entityManagerFactory definition


I had a working code with Spring -Jpa . Recently I had a requirement where I had to add multiple datasource and for the same I had to define the entityManagerFactory(Code given below) . Since the time I added this entity(Table) is not created automatically or is not recognized by appication. My Project is using Spring parent 2.7.13 . I tried it with newer version of Spring(3.1.3) and it works fine. Can someone help me out what is the issue and is there something I am missing. I have validated the packages and it is fine. Also before this new class being added it was working fine.

@Configuration
public class DataSourceConfig {

    // Primary datasource configuration

    @Primary
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("primaryDataSource") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.demo.model") // base package for your JPA entities
                .persistenceUnit("primary")
                .build();
    }

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

    // Secondary Datasource 1 Configuration

    @Bean(name = "secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.ds1")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondaryJdbcTemplate")
    public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    // Secondary Datasource 2 Configuration

    @Bean(name = "thirdDataSource")
    @ConfigurationProperties(prefix = "spring.ds2")
    public DataSource thirdDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "thirdJdbcTemplate")
    public JdbcTemplate thirdJdbcTemplate(@Qualifier("thirdDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

Solution

  • The way that worked for me is:

    1. I created a folder for each database/user that i want my app to connect.For example if you want to connect to 2 databases (db1, db2) i created 2 folders db1 and db2.

    2. Inside those folders i created an Entity folder (where i put the corresponding to the database entities), a Repository folder, a Service folder and a Config folder.

    3. In the Config folder i created the DB1_Config.java file (DB1_Config for db1, DB2_Config for db2)

    4. The DB1_Config.java file looks like this

      @Configuration
      @EnableTransactionManagement
      @EnableJpaRepositories(
           entityManagerFactoryRef = "DB1userEntityManagerFactory",
           transactionManagerRef = "DB1userTransactionManager",
           basePackages = {"com.DataBase.DB1.user.Repository"}) //put the actual path to your Repository folder
      public class DB1_Config{
      
       static final String JNDI = "jdbc/DB1user"; //your actual jndi name
      
       @Bean(name = "DB1userDataSource", destroyMethod = "")
       @ConfigurationProperties(prefix = "DB1user.datasource")
       public DataSource dataSource() throws DataSourceLookupFailureException {
           JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
           return dataSourceLookup.getDataSource(JNDI);
       }
      
       @Bean(name = "DB1userEntityManagerFactory")
       public LocalContainerEntityManagerFactoryBean
               entityManagerFactory(
                       EntityManagerFactoryBuilder builder,
                       @Qualifier("DB1userDataSource") DataSource dataSource) {
           return builder.dataSource(dataSource).packages("com.DataBase.DB1.user.Entity").persistenceUnit("db1user").build();
       } //in com.DataBase.DB1.user.Entity put your actual Entity path
      
       @Bean(name = "DB1userTransactionManager")
       public PlatformTransactionManager entityTransactionManager(
               @Qualifier("DB1userEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
           return new JpaTransactionManager(entityManagerFactory);
       }
      }
      

    And DB2_Config the same but wherever it writes DB1 you put DB2. I think the main problem is that you have to group your classes depending on the different databases or if you are on the same database on the different schema users.