Skip to content

Instantly share code, notes, and snippets.

@dakoctba
Last active January 22, 2024 11:58
Show Gist options
  • Save dakoctba/1047ca084118ff46a1a917726f99a2b2 to your computer and use it in GitHub Desktop.
Save dakoctba/1047ca084118ff46a1a917726f99a2b2 to your computer and use it in GitHub Desktop.
Spring Boot + JDBI + Multiple Databases
import java.util.List;
import javax.sql.DataSource;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.core.mapper.RowMapper;
import org.jdbi.v3.core.spi.JdbiPlugin;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import br.com.company.produto.dao.dominio.CityDAO;
import br.com.company.produto.dao.dw.ProfessionDAO;
@Configuration
public class AppConfig {
@Bean("jdbi-1")
public Jdbi jdbi(@Qualifier("datasource1") DataSource ds, List<JdbiPlugin> plugins, List<RowMapper<?>> mappers) {
TransactionAwareDataSourceProxy proxy = new TransactionAwareDataSourceProxy(ds);
Jdbi jdbi = Jdbi.create(proxy);
plugins.forEach(plugin -> jdbi.installPlugin(plugin));
mappers.forEach(mapper -> jdbi.registerRowMapper(mapper));
return jdbi;
}
@Bean("jdbi-2")
public Jdbi secondaryJdbi(@Qualifier("datasource2") DataSource ds, List<JdbiPlugin> plugins, List<RowMapper<?>> mappers) {
TransactionAwareDataSourceProxy proxy = new TransactionAwareDataSourceProxy(ds);
Jdbi jdbi = Jdbi.create(proxy);
plugins.forEach(plugin -> jdbi.installPlugin(plugin));
mappers.forEach(mapper -> jdbi.registerRowMapper(mapper));
return jdbi;
}
@Bean
public JdbiPlugin sqlObjectPlugin() {
return new SqlObjectPlugin();
}
@Bean
public CityDAO cityDao(@Qualifier("jdbi-1") Jdbi jdbi) {
return jdbi.onDemand(CityDAO.class);
}
@Bean
public ProfessionDAO professionDao(@Qualifier("jdbi-2") Jdbi jdbi) {
return jdbi.onDemand(ProfessionDAO.class);
}
}
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
spring.jpa.database=default
#
# Primary database
#
spring.datasource.db1.jdbcUrl=jdbc:postgresql://localhost:5432/<database>
spring.datasource.db1.driver-class-name=org.postgresql.Driver
spring.datasource.db1.username=postgres
spring.datasource.db1.password=postgres
#
# Secondary database
#
spring.datasource.db2.jdbcUrl=jdbc:postgresql://localhost:5432/<database>
spring.datasource.db2.driver-class-name=org.postgresql.Driver
spring.datasource.db2.username=postgres
spring.datasource.db2.password=postgres
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration
public class DataSourceConfig {
@Bean(name = "datasource1")
@ConfigurationProperties("spring.datasource.db1")
@Primary
public DataSource db1Datasource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "datasource2")
@ConfigurationProperties("spring.datasource.db2")
public DataSource db2Datasource() {
return DataSourceBuilder.create().build();
}
@Bean(name="tm1")
@Autowired
@Primary
DataSourceTransactionManager tm1(@Qualifier ("datasource1") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
@Bean(name="tm2")
@Autowired
DataSourceTransactionManager tm2(@Qualifier ("datasource2") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
}
@thiagomuller
Copy link

Nice!!

@d2k2-git
Copy link

d2k2-git commented Jan 14, 2024

can you explain for what the DataSourceTransactionManager Bean is required for?
From my experience it's enough to use TransactionAwareDataSourceProxy to make springs @Transactional annotation working with jdbi.

Also according to the jdbi documention you should use Spring SpringConnectionFactory instead TransactionAwareDataSourceProxy to create a JDBI bean instance.

see: https://jdbi.org/#_annotation_based_configuration

@Configuration
public class JdbiConfiguration {
    @Bean
    public Jdbi jdbi(DataSource ds) {
        ConnectionFactory cf = new SpringConnectionFactory(dataSource); 
        final Jdbi jdbi = Jdbi.create(cf);
        /* additional configuration goes here */
        return jdbi;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment