Dans la prochaine version de Spring Data, nommée Lovelace, nous allons inclure un nouveau module: Spring Data JDBC .
L'idée derrière Spring Data JDBC est de fournir un accès aux bases de données relationnelles sans utiliser toute la complexité de JPA .
JPA offre des fonctionnalités telles que le chargement différé , la mise en cache et le suivi des modifications (suivi incorrect). Malgré le fait que ces fonctionnalités soient très intéressantes, si vous en avez vraiment besoin, bien sûr, elles peuvent grandement compliquer la compréhension de la logique d'accès aux données.
Le mécanisme de chargement différé peut soudainement exécuter des requêtes gourmandes en ressources, voire échouer avec une exception. La mise en cache peut vous gêner lorsque vous décidez de comparer deux versions d'une entité, et couplée au suivi des modifications, elle est plus difficile à comprendre - à quel moment toutes les opérations de base de données seront-elles réellement terminées?
Spring Data JDBC se concentre sur un modèle beaucoup plus simple . Il n'y aura pas de mise en cache, de suivi des modifications ou de chargement paresseux. Au lieu de cela, les requêtes SQL seront exécutées si et seulement si vous appelez la méthode du référentiel. Le résultat renvoyé sera entièrement chargé en mémoire après l'exécution de la méthode. Il n'y aura pas de mécanisme de «session» ni d'objets proxy pour les entités. Et tout cela devrait faire de Spring Data JDBC un outil plus simple et plus intuitif pour accéder aux données.
Bien sûr, une telle approche simplifiée se traduit par un certain nombre de limitations, dont nous parlerons dans les prochains articles. La prochaine version est la toute première version de la bibliothèque, nous avons de nombreux plans et idées que nous voulons mettre en œuvre, mais nous devons les reporter pour vous donner la possibilité de commencer à utiliser Spring Data JDBC le plus tôt possible.
Exemple
Pour commencer, nous devons définir une entité:
class Customer { @Id Long id; String firstName; LocalDate dob; }
Veuillez noter que nous ne définissons ni getters ni setters. Bien sûr, vous pouvez les ajouter si vous le souhaitez. En substance, la seule exigence pour une entité est d'avoir le champ annoté avec une annotation Id
(mais à savoir org.springframework.data.annotation.Id
, pas javax.persistence one
).
Ensuite, vous devez définir le référentiel. La façon la plus simple de procéder consiste à étendre l'interface CrudRepository
.
interface CustomerRepository extends CrudRepository<Customer, Long> {}
Enfin, vous devez configurer ApplicationContext
pour que l'implémentation de cette interface soit créée automatiquement:
@Configuration @EnableJdbcRepositories (1) public class CustomerConfig extends JdbcConfiguration { (2) @Bean NamedParameterJdbcOperations operations() { (3) return new NamedParameterJdbcTemplate(dataSource()); } @Bean PlatformTransactionManager transactionManager() { (4) return new DataSourceTransactionManager(dataSource()); } @Bean DataSource dataSource(){ (5) return new EmbeddedDatabaseBuilder() .generateUniqueName(true) .setType(EmbeddedDatabaseType.HSQL) .addScript("create-customer-schema.sql") .build(); } }
Analysons la configuration plus en détail.
EnableJdbcRepositories
la création automatique de référentiel. Pour que cela fonctionne, vous devez fournir plusieurs beans supplémentaires, qui nécessiteront le reste de notre classe de configuration.- Parce que la classe de configuration étend
JdbcConfiguration
, plusieurs beans seront automatiquement ajoutés au contexte. Vous pouvez également les chevaucher si vous devez modifier le comportement de Spring Data JDBC. Mais dans cet exemple, nous laisserons le comportement par défaut. - Un composant très important est
NamedParameterJdbcOperations
, qui est utilisé pour effectuer des requêtes de base de données. - Un gestionnaire de transactions, à proprement parler, n'est pas requis. Mais sans cela, il n'y aura pas de support de transaction, et peu de gens l'aimeront, non?
- Spring Data JDBC n'utilise pas directement
DataSource
, mais TransactionManager
et NamedParameterJdbcOperation
nécessitent sa présence dans le contexte, c'est pourquoi nous déterminons le bean souhaité.
C'est tout ce qu'il faut pour commencer avec Spring Data JDBC. Maintenant, écrivez un test pour voir comment tout cela fonctionne:
@RunWith(SpringRunner.class) @Transactional @ContextConfiguration(classes = CustomerConfig.class) public class CustomerRepositoryTest { @Autowired CustomerRepository customerRepo; @Test public void createSimpleCustomer() { Customer customer = new Customer(); customer.dob = LocalDate.of(1904, 5, 14); customer.firstName = "Albert"; Customer saved = customerRepo.save(customer); assertThat(saved.id).isNotNull(); saved.firstName = "Hans Albert"; customerRepo.save(saved); Optional<Customer> reloaded = customerRepo.findById(saved.id); assertThat(reloaded).isNotEmpty(); assertThat(reloaded.get().firstName).isEqualTo("Hans Albert"); } }
@Query
Ce n'est qu'avec les méthodes CRUD standard que vous pouvez vous CrudRepository
référentiel de classes CrudRepository
. Nous avons délibérément décidé de reporter la génération automatique de requêtes - une caractéristique populaire de Spring Data, lorsque des requêtes SQL sont générées en fonction du nom de la méthode - pour les versions futures. Et pour l'instant, vous pouvez simplement utiliser l'annotation @Query
familière pour spécifier exactement quelle requête SQL doit être exécutée.
@Query("select id, first_name, dob from customer where upper(first_name) like '%' || upper(:name) || '%' ") List<Customer> findByName(@Param("name") String name);
Si vous souhaitez modifier ou supprimer des données dans la demande, vous pouvez ajouter l'annotation @Modifying
à la méthode.
Écrivons un test pour voir comment fonctionne notre nouvelle méthode.
@Test public void findByName() { Customer customer = new Customer(); customer.dob = LocalDate.of(1904, 5, 14); customer.firstName = "Albert"; Customer saved = customerRepo.save(customer); assertThat(saved.id).isNotNull(); customer.id= null; (1) customer.firstName = "Bertram"; customerRepo.save(customer); customer.id= null; customer.firstName = "Beth"; customerRepo.save(customer); assertThat(customerRepo.findByName("bert")).hasSize(2); (2) }
- Parce que Étant donné que la connexion entre les objets Java et l'enregistrement dans la base de données se fait uniquement par champ et type
Id
, la définition de Id
sur null
et l'enregistrement de cet objet créeront un nouvel enregistrement. - Dans la demande, nous utilisons des caractères sensibles à la casse, et donc nous trouvons «Albert» et «Bertram», mais pas «Beth».
En conclusion
Bien sûr, beaucoup plus peut être dit sur Spring Data JDBC, et nous vous le dirons certainement dans les prochains articles.
En attendant, vous pouvez étudier l'exemple de code , la documentation et, bien sûr, le code source . Si vous avez des questions, n'hésitez pas à les poser sur StackOverflow . Et si vous trouvez un bug ou souhaitez demander une nouvelle fonctionnalité - veuillez créer un ticket .