How to create Custom DataSource in Spring Boot + Spring Data

13,239

Solution 1

No need to exclude the built in autoconfiguration.

In you application.yml

myapp:
     datasource:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/mydb?autoReconnect=true&characterEncoding=utf8
        username: myuser
        # make sure you exclude password from here

And in your configuration:

// all the other datasource properties will be applied from "myapp.datasource" except password because you excluded it
@ConfigurationProperties(prefix = "myapp.datasource")
@Bean
@Primary // this will override the datasource autoconfiguration and use your own everywhere
public DataSource dataSource() {
    String password = retrieveMyPasswordSecurely();

    return DataSourceBuilder
        .create()
          .password(password)
        .build();
}

Solution 2

You need to provide an Entity Manager Factory bean. You can follow the convention of creating a bean with the name entityManagerFactory, assuming that you don't already have one. There's a few examples in the Spring documentation here and here.

Assuming you've got a data source, you might be able to get away with as little as this:

@Configuration
public class Database {
  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);

    LocalContainerEntityManagerFactoryBean factory =
      new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("org.yourcompany.jpaentityroot");
    factory.setDataSource(dataSource);
    return factory;
  }

  @Bean
  public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(emf);
    return txManager;
  }

  @Resource private DataSource dataSource;
}
Share:
13,239

Related videos on Youtube

Arun Avanathan
Author by

Arun Avanathan

Updated on June 04, 2022

Comments

  • Arun Avanathan
    Arun Avanathan almost 2 years

    I want to create Custom DataSource programmatically. This is because I want to fetch password from a secure storage at runtime, instead of hardcoding it in application.yaml.

    I have a custom datasource - myapp.datasource.password which has the value of mydb.password.key. Using ApplicationListener I am loading secrets and setting the value of myapp.datasource.password using mydb.password.key as key.

    myapp:
         datasource:
            driverClassName: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/mydb?autoReconnect=true&characterEncoding=utf8
            username: myuser
            password: mydb.password.key
    

    Now, HibernateJpaAutoConfiguration is trying to connect to DB using mydb.password.key as password and failing at the time of startup.

    I tried to exclude DB auto configuration classes

    @SpringBootApplication
        (exclude={
        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class
        })
    

    But it throws this exception

    org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available

    How to resolve this? Any help is greatly appreciated!

    Thanks

  • Arun Avanathan
    Arun Avanathan over 6 years
    Thanks. This solution fixed the problem!
  • Arun Avanathan
    Arun Avanathan over 6 years
    Thanks @PaulHicks. We wanted to keep the config, implementation (Hibernate) agnostic. Hence, didn't take this route.