Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

[Dúvida] 2 DB postgres no spring boot (dataSource or dataSourceClassName or jdbcUrl is required)

Usando como exemplo o tópico: https://cursos.alura.com.br/forum/topico-multiplos-datasources-76362, tentei conectar em dois BD postgres, no entanto, ocorre o erro:

java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
    at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:1029) ~[HikariCP-4.0.3.jar:na]
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:109) ~[HikariCP-4.0.3.jar:na]
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
2023-03-21 12:29:14.658  INFO 19996 --- [  restartedMain] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-03-21 12:29:14.674 ERROR 19996 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authEntityManagerFactory' defined in class path resource [com/acreprev/multibd/config/AuthDbConfig.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.25.jar:5.3.25]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:272) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
    ... 38 common frames omitted
 ###### O meu application.properties:

 // configurações para o banco de dados "b1"

spring.datasource.url=jdbc:postgresql://localhost:5432/b1
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.jdbcUrl=${spring.datasource.url}

// configurações para o banco de dados "b2"

b2.datasource.url=jdbc:postgresql://localhost:5432/b2
b2.spring.datasource.username=postgres
b2.spring.datasource.password=postgres
b2.spring.datasource.driver-class-name=org.postgresql.Driver
b2.datasource.jdbcUrl=${ctc.datasource.url}

As demais classes são igual ao topico citado, Alguma Luz? ultilizo o Spring 2.7

3 respostas

Mesma dúvida cara

solução!

Consegui resolver uns dias atrás, segue o cód.:

application.properties:

#Configuração do BD 1
spring.datasource.jdbc-url=jdbc:postgresql://localhost:5432/bd1?currentSchema=bd1
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driverClassName=org.postgresql.Driver

#Configuração do BD 2
db2.datasource.jdbc-url=jdbc:postgresql://localhost:5432/bd2?currentSchema=bd1
db2.datasource.username=postgres
db2.datasource.password=postgres
db2.datasource.driverClassName=org.postgresql.Driver

Você cria um pacote para a configuração de cada BD (Exemplo: package com.dbs.db1.config), a classe abaixo será meu BD principal :

package com.dbs.db1.config;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "bd1EntityManagerFactory", transactionManagerRef = "bd1TransactionManager", basePackages = {
        "com.dbs.bd1.repository" }) // Aqui será onde vai ficar os Repository do BD 1
public class B1Config {

    @Primary
    @Bean(name = "bd1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource") // Aqui ele informa as informações trazidas do application.properties
    public DataSource customerDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean(name = "bd1EntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
            @Qualifier("bd1DataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("com.dbs.bd1.model").persistenceUnit("db1") // Aqui será onde vai ficar as Entitys do BD 1
                .build();
    }

    @Primary
    @Bean(name = "bd1TransactionManager")
    public PlatformTransactionManager customerTransactionManager(
            @Qualifier("bd1EntityManagerFactory") EntityManagerFactory customerEntityManagerFactory) {
        return new JpaTransactionManager(customerEntityManagerFactory);
    }
}

A classe a seguir é a configuração do segundo BD2 (package com.dbs.db2.config):

package com.dbs.db2.config;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "bd2EntityManagerFactory", transactionManagerRef = "bd2TransactionManager", basePackages = {
        "com.dbs.bd2.repository" })  // Aqui será onde vai ficar os Repository do BD 2
public class B2Config {

    @Bean(name = "bd2DataSource")
    @ConfigurationProperties(prefix = "db2.datasource") // Aqui ele informa as informações trazidas do application.properties
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "bd2EntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean barEntityManagerFactory(EntityManagerFactoryBuilder builder,
            @Qualifier("bd2DataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("com.dbs.bd2.model").persistenceUnit("db2")  // Aqui será onde vai ficar as Entitys do BD 1
                .build();
    }

    @Bean(name = "bd2TransactionManager")
    public PlatformTransactionManager productTransactionManager(
            @Qualifier("bd2EntityManagerFactory") EntityManagerFactory bd2EntityManagerFactory) {
        return new JpaTransactionManager(bd2EntityManagerFactory);
    }
}

Agora só criar as @Entity e os @Repository :

Continuação (@Entity e os @Repository):

Tabela que tem no BD1 (com.dbs.bd1.model):

@Entity
public class Usuario implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "nome")
    private String nome;

    /* GET / SET */

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

}

Tabela que temos no BD2 (com.dbs.bd2.model):

@Entity
public class Livro implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "nome")
    private String nome;

    /* GET / SET */

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

}

Agora os @Repository do DB1 (com.dbs.bd1.repository):

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.dbs.bd1.model.Usuario;

@Repository
public interface UsuarioRepository extends JpaRepository<Usuario, Long> {

}

Livro @Repository do DB2 (com.dbs.bd2.repository):

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.dbs.bd2.model.Livro;

@Repository
public interface LivroRepository extends JpaRepository<Livro, Long> {

}

Pronto, o spring vai gerencia-los, agora veja se já tá fazendo as conexões, crie um controller e veja:


import com.dbs.bd1.model.Usuario;
import com.dbs.bd2.model.Livro;

import com.dbs.bd1.repository.UsuarioRepository
import com.dbs.bd2.repository.LivroRepository;

@RestController
public class ConexaoController {

    @Autowired
    private UsuarioRepository usuarioRepository;

    @Autowired
    private LivroRepository livroRepository;

    @GetMapping("/users")
    public List<Usuario> user() {    
        return usuarioRepository.findAll();
    }

    @GetMapping("/livro")
    public List<Livro> servidor() {    
        return livroRepository.findAll();
    }

}

Acesse a URL do @GetMapping e pronto.