Configurazione di un'origine dati a livello di codice in Spring Boot

1. Panoramica

Spring Boot utilizza un algoritmo supponente per cercare e configurare un DataSource . Questo ci consente di ottenere facilmente un'implementazione DataSource completamente configurata per impostazione predefinita.

Inoltre, Spring Boot configura automaticamente un pool di connessioni velocissimo: HikariCP, Apache Tomcat o Commons DBCP, in quest'ordine, a seconda di quale si trova nel percorso di classe.

Sebbene la configurazione automatica di DataSource di Spring Boot funzioni molto bene nella maggior parte dei casi, a volte avremo bisogno di un livello di controllo più elevato , quindi dovremo impostare la nostra implementazione DataSource , saltando quindi il processo di configurazione automatica.

In questo tutorial impareremo come configurare un DataSource a livello di codice in Spring Boot .

2. Le dipendenze di Maven

La creazione di un'implementazione DataSource a livello di codice è semplice, nel complesso .

Per sapere come ottenere ciò, implementeremo un semplice livello di repository, che eseguirà operazioni CRUD su alcune entità JPA.

Diamo un'occhiata alle dipendenze del nostro progetto demo:

 org.springframework.boot spring-boot-starter-data-jpa   com.h2database h2 2.4.1 runtime 

Come mostrato sopra, useremo un'istanza di database H2 in memoria per esercitare il livello del repository. In tal modo, saremo in grado di testare il nostro DataSource configurato in modo programmatico , senza il costo di eseguire costose operazioni di database.

Inoltre, assicuriamoci di controllare l'ultima versione di spring-boot-starter-data-jpa su Maven Central.

3. Configurazione di un'origine dati a livello di programmazione

Ora, se ci atteniamo alla configurazione automatica DataSource di Spring Boot ed eseguiamo il nostro progetto nel suo stato corrente, funzionerà come previsto.

Spring Boot farà tutto l'impianto idraulico delle infrastrutture pesanti per noi. Ciò include la creazione di un'implementazione H2 DataSource , che verrà gestita automaticamente da HikariCP, Apache Tomcat o Commons DBCP e la configurazione di un'istanza di database in memoria.

Inoltre, non avremo nemmeno bisogno di creare un file application.properties , poiché Spring Boot fornirà anche alcune impostazioni di database predefinite.

Come accennato in precedenza, a volte avremo bisogno di un livello di personalizzazione più elevato, quindi dovremo configurare a livello di programmazione la nostra implementazione DataSource .

Il modo più semplice per ottenere ciò è definire un metodo factory DataSource e posizionarlo all'interno di una classe annotata con l' annotazione @Configuration :

@Configuration public class DataSourceConfig { @Bean public DataSource getDataSource() { DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); dataSourceBuilder.driverClassName("org.h2.Driver"); dataSourceBuilder.url("jdbc:h2:mem:test"); dataSourceBuilder.username("SA"); dataSourceBuilder.password(""); return dataSourceBuilder.build(); } }

In questo caso, abbiamo utilizzato la comoda classe DataSourceBuilder , una versione non fluente del pattern builder di Joshua Bloch, per creare programmaticamente il nostro oggetto DataSource personalizzato .

Questo approccio è davvero utile perché il builder semplifica la configurazione di un DataSource utilizzando alcune proprietà comuni. Inoltre, utilizza anche il pool di connessioni sottostante.

4. Esternalizzazione della configurazione dell'origine dati con il file application.properties

Ovviamente è anche possibile esternalizzare parzialmente la nostra configurazione DataSource . Ad esempio, potremmo definire alcune proprietà DataSource di base nel nostro metodo factory:

@Bean public DataSource getDataSource() { DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); dataSourceBuilder.username("SA"); dataSourceBuilder.password(""); return dataSourceBuilder.build(); }

E specificarne alcuni aggiuntivi nel file application.properties :

spring.datasource.url=jdbc:h2:mem:test spring.datasource.driver-class-name=org.h2.Driver 

Le proprietà definite in un'origine esterna, come il file application.properties sopra o tramite una classe annotata con @ConfigurationProperties , sovrascriveranno quelle definite nell'API Java.

Diventa evidente che, con questo approccio, non manterremo più le nostre impostazioni di configurazione DataSource archiviate in un unico posto .

D'altra parte, ci consente di mantenere le impostazioni di configurazione in fase di compilazione e in fase di esecuzione ben separate l'una dall'altra.

Questo è davvero buono, poiché ci consente di impostare facilmente un punto di associazione della configurazione. In questo modo possiamo includere diverse impostazioni di DataSource da altre fonti, senza dover rifattorizzare i nostri metodi di bean factory.

5. Verifica della configurazione DataSource

Testare la nostra configurazione DataSource personalizzata è molto semplice. L'intero processo si riduce alla creazione di un'entità JPA, alla definizione di un'interfaccia di base del repository e al test del livello del repository.

5.1. Creazione di un'entità JPA

Iniziamo definendo la nostra classe di entità JPA di esempio, che modellerà gli utenti:

@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String name; private String email; // standard constructors / setters / getters / toString }

5.2. Un semplice livello di repository

Successivamente, dobbiamo implementare un livello di repository di base, che ci consenta di eseguire operazioni CRUD su istanze della classe di entità User definita sopra.

Poiché utilizziamo Spring Data JPA, non è necessario creare da zero la nostra implementazione DAO. Dobbiamo semplicemente estendere l' interfaccia CrudRepository per ottenere un'implementazione del repository funzionante:

@Repository public interface UserRepository extends CrudRepository {} 

5.3. Testare il livello del repository

Infine, dobbiamo verificare che il nostro DataSource configurato in modo programmatico funzioni effettivamente. Possiamo facilmente farlo con un test di integrazione:

@RunWith(SpringRunner.class) @DataJpaTest public class UserRepositoryIntegrationTest { @Autowired private UserRepository userRepository; @Test public void whenCalledSave_thenCorrectNumberOfUsers() { userRepository.save(new User("Bob", "[email protected]")); List users = (List) userRepository.findAll(); assertThat(users.size()).isEqualTo(1); } }

La classe UserRepositoryIntegrationTest è piuttosto autoesplicativa. Esercita semplicemente due dei metodi CRUD dell'interfaccia del repository per persistere e trovare entità.

Notice that regardless of whether we decide to programmatically configure our DataSource implementation, or split it into a Java config method and the application.properties file, we should always get a working database connection.

5.4. Running the Sample Application

Finally, we can run our demo application using a standard main() method:

@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public CommandLineRunner run(UserRepository userRepository) throws Exception { return (String[] args) -> { User user1 = new User("John", "[email protected]"); User user2 = new User("Julie", "[email protected]"); userRepository.save(user1); userRepository.save(user2); userRepository.findAll().forEach(user -> System.out.println(user); }; } } 

We already tested the repository layer, so we're sure that our DataSource has been configured successfully. Thus, if we run the sample application, we should see in our console output the list of User entities stored in the database.

6. Conclusion

In questo tutorial abbiamo imparato come configurare un'implementazione DataSource a livello di codice in Spring Boot .

Come al solito, tutti gli esempi di codice mostrati in questo tutorial sono disponibili su GitHub.