Configurer un DataSource par programme dans Spring Boot

1. Vue d'ensemble

Spring Boot utilise un algorithme avisé pour rechercher et configurer une source de données . Cela nous permet d'obtenir facilement une implémentation DataSource entièrement configurée par défaut.

De plus, Spring Boot configure automatiquement un pool de connexions ultra-rapide - HikariCP, Apache Tomcat ou Commons DBCP, dans cet ordre, en fonction de ce qui se trouve sur le chemin de classe.

Bien que la configuration automatique de DataSource de Spring Boot fonctionne très bien dans la plupart des cas, nous aurons parfois besoin d'un niveau de contrôle plus élevé , nous devrons donc configurer notre propre implémentation DataSource , évitant ainsi le processus de configuration automatique.

Dans ce didacticiel, nous allons apprendre à configurer un DataSource par programmation dans Spring Boot .

2. Les dépendances de Maven

La création d'une implémentation DataSource par programme est simple, dans l'ensemble .

Pour savoir comment y parvenir, nous allons implémenter une couche de référentiel simple, qui effectuera des opérations CRUD sur certaines entités JPA.

Jetons un coup d'œil aux dépendances de notre projet de démonstration:

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

Comme indiqué ci-dessus, nous utiliserons une instance de base de données H2 en mémoire pour exercer la couche de référentiel. Ce faisant, nous serons en mesure de tester notre DataSource configurée par programme , sans le coût des opérations de base de données coûteuses.

De plus, assurons-nous de vérifier la dernière version de spring-boot-starter-data-jpa sur Maven Central.

3. Configuration d'un DataSource par programme

Maintenant, si nous nous en tenons à la configuration automatique de DataSource de Spring Boot et exécutons notre projet dans son état actuel, il fonctionnera comme prévu.

Spring Boot s'occupera de toute la plomberie de l'infrastructure lourde pour nous. Cela inclut la création d'une implémentation H2 DataSource , qui sera automatiquement gérée par HikariCP, Apache Tomcat ou Commons DBCP, et la configuration d'une instance de base de données en mémoire.

De plus, nous n'aurons même pas besoin de créer un fichier application.properties , car Spring Boot fournira également certains paramètres de base de données par défaut.

Comme nous l'avons mentionné précédemment, nous aurons parfois besoin d'un niveau de personnalisation plus élevé, nous devrons donc configurer par programme notre propre implémentation DataSource .

Le moyen le plus simple d'y parvenir consiste à définir une méthode de fabrique DataSource et à la placer dans une classe annotée avec l' annotation @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(); } }

Dans ce cas, nous avons utilisé la classe de commodité DataSourceBuilder - une version non fluide du modèle de générateur de Joshua Bloch - pour créer par programme notre objet DataSource personnalisé .

Cette approche est vraiment intéressante car le générateur facilite la configuration d'une source de données en utilisant certaines propriétés communes. En outre, il utilise également le pool de connexions sous-jacent.

4. Externalisation de la configuration de DataSource avec le fichier application.properties

Bien entendu, il est également possible d'externaliser partiellement notre configuration DataSource . Par exemple, nous pourrions définir certaines propriétés de base de DataSource dans notre méthode d'usine:

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

Et spécifiez-en quelques-uns supplémentaires dans le fichier application.properties :

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

Les propriétés définies dans une source externe, comme le fichier application.properties ci-dessus ou via une classe annotée avec @ConfigurationProperties , remplaceront celles définies dans l'API Java.

Il devient évident qu'avec cette approche, nous ne conserverons plus nos paramètres de configuration DataSource stockés en un seul endroit .

D'autre part, cela nous permet de garder les paramètres de configuration au moment de la compilation et de l'exécution bien séparés les uns des autres.

C'est vraiment bien, car cela nous permet de définir facilement un point de liaison de configuration. De cette façon, nous pouvons inclure différents paramètres DataSource provenant d'autres sources, sans avoir à refactoriser nos méthodes de fabrique de haricots.

5. Test de la configuration DataSource

Le test de notre configuration DataSource personnalisée est très simple. L'ensemble du processus se résume à créer une entité JPA, à définir une interface de référentiel de base et à tester la couche de référentiel.

5.1. Création d'une entité JPA

Commençons par définir notre exemple de classe d'entité JPA, qui modélisera les utilisateurs:

@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. Une couche de référentiel simple

Ensuite, nous devons implémenter une couche de référentiel de base, qui nous permet d'effectuer des opérations CRUD sur des instances de la classe d'entité User définie ci-dessus.

Puisque nous utilisons Spring Data JPA, nous n'avons pas à créer notre propre implémentation DAO à partir de zéro. Nous devons simplement étendre l' interface CrudRepository pour obtenir une implémentation de référentiel fonctionnelle:

@Repository public interface UserRepository extends CrudRepository {} 

5.3. Test de la couche du référentiel

Enfin, nous devons vérifier que notre DataSource configurée par programme fonctionne réellement. Nous pouvons facilement y parvenir avec un test d'intégration:

@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 est assez explicite. Il exerce simplement deux des méthodes CRUD de l'interface du référentiel pour persister et trouver des entités.

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

Dans ce didacticiel, nous avons appris à configurer une implémentation DataSource par programme dans Spring Boot .

Comme d'habitude, tous les exemples de code présentés dans ce didacticiel sont disponibles à l'adresse over sur GitHub.