WojteMac
WojteMac

Reputation: 21

Spring boot connection to more then 2 data source

I'm currently working on Spring Boot project where I need to connect to more than 2 data source (actually 4). I found many examples how to connect to 2 DS and it works, but when I add next in the same way it's not working:

...Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class...

Is there any restriction on data sources? Or is it possible to connect to more than 2 DS?

Upvotes: 1

Views: 1099

Answers (3)

WojteMac
WojteMac

Reputation: 21

Thanks for your help. Actually I did all configuration right but ... (one small misspell crash all :)) As I was starting including my code I found it, fixed and now all works fine. But here is my code as example (maybe someone will use it :))

All three entities and repositories (Shadow, Main, Project) are configured exactly in the same way so I put it only once. (the only differences is that DS for Main is as @Primary.

Thanks. BR

application.properties

#-------------------------- first
spring.datasource.url=jdbc:mysql://
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#-------------------------- second
second.datasource.url=jdbc:mysql://
second.datasource.username=
second.datasource.password=
second.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#-------------------------- third
third.datasource.url=jdbc:mysql://
third.datasource.password=
third.datasource.username=
third.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Shadow.java

package com.server.shadow.domain;

import ...

@Entity
@Table(name = "shadow")
public class Shadow {

    @Id
    private String id;
    private String shadow;

    public Shadow(){}

   //getters and setters
}

ShadowRepository.java

package com.server.shadow.repo;

import ...

@Repository
public interface ShadowRepository extends JpaRepository<Shadow,Long> {
}

ShadowDbConf.java

package com.server;

import ...

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "shadowEntityManagerFactory",
        transactionManagerRef = "shadowTransactionManager",
        basePackages = {"com.server.shadow.repo"}
)
public class ShadowDbConf {

     @Bean(name = "shadowDataSource")
    @ConfigurationProperties(prefix = "second.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "shadowEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean
    shadowEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("shadowDataSource") DataSource dataSource
    ) {
        return
                builder
                        .dataSource(dataSource)
                        .packages("com.server.shadow.domain")
                        .persistenceUnit("shadow")
                        .build();
    }
    @Bean(name = "shadowTransactionManager")
    public PlatformTransactionManager shadowTransactionManager(
            @Qualifier("shadowEntityManagerFactory") EntityManagerFactory
                    shadowEntityManagerFactory
    ) {
        return new JpaTransactionManager(shadowEntityManagerFactory);
    }
}

MainController.java

package com.server;

import ...

@RestController
public class MainController {

    private final ShadowRepository shadowRepository;
    private final MainRepository mainRepository;
    private final PojectRepository projectRepository;

    @Autowired
    MainController(ShadowRepository shadowRepository, MainRepository mainRepository,PojectRepository projectRepository) {
        this.shadowRepository = shadowRepository;
        this.mainRepository = mainRepository;
        this.projectRepository = projectRepository;
    }

    @GetMapping(path = "/shadow")
    public @ResponseBody Iterable<Shadow> getShadows(){
        return shadowRepository.findAll();
    }
}

Upvotes: 0

Rakshith R Pai
Rakshith R Pai

Reputation: 192

Adding to what @Surya said

Step 1: Set up the data base configuration in application.properties file as mentioned above.

Step 2:You need to create a bean.In your case u need to create 2 separate bean pointing to 2 diff data source.

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


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

U can create this 2 bean in a single class.

Now wondering how to use this bean!

@Autowired
  @Qualifier("firstds")
  NamedParameterJdbcTemplate            firstConnection;
 result = firstConnection.query(Your query goes here)

Above query will always hit first db via the bean you created. Similarly you can use connection to hit db 2 via the second bean.

Upvotes: 0

surya
surya

Reputation: 2749

Create as many datasource you want. No restrictions i am aware of. It is just another bean .Refer here

#first db
spring.datasource.url = [url]
spring.datasource.username = [username]
spring.datasource.password = [password]
spring.datasource.driverClassName = oracle.jdbc.OracleDriver

#second db ...
spring.secondDatasource.url = [url]
spring.secondDatasource.username = [username]
spring.secondDatasource.password = [password]
spring.secondDatasource.driverClassName = oracle.jdbc.OracleDriver


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

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

Upvotes: 3

Related Questions