Introduzione a Spring Data JPA

1. Panoramica

Questo articolo si concentrerà sull'introduzione di Spring Data JPA in un progetto Spring e sulla configurazione completa del livello di persistenza. Per un'introduzione passo passo sulla configurazione del contesto Spring utilizzando la configurazione basata su Java e il Maven pom di base per il progetto, vedere questo articolo.

2. DAO Spring Data Generated - Niente più implementazioni DAO

Come abbiamo discusso in un articolo precedente, il livello DAO di solito è costituito da molto codice boilerplate che può e deve essere semplificato. I vantaggi di una tale semplificazione sono molti: una diminuzione del numero di artefatti che dobbiamo definire e mantenere, coerenza dei modelli di accesso ai dati e coerenza della configurazione.

Spring Data porta questa semplificazione un passo avanti e rende possibile rimuovere completamente le implementazioni DAO . L'interfaccia del DAO è ora l'unico artefatto che dobbiamo definire in modo esplicito.

Per iniziare a sfruttare il modello di programmazione Spring Data con JPA, un'interfaccia DAO deve estendere l' interfaccia del repository specifica JPA - JpaRepository . Ciò consentirà a Spring Data di trovare questa interfaccia e di crearne automaticamente un'implementazione.

Estendendo l'interfaccia otteniamo i metodi CRUD più rilevanti per l'accesso ai dati standard disponibili in un DAO standard.

3. Metodo di accesso personalizzato e query

Come discusso, implementando una delle interfacce del repository , DAO avrà già alcuni metodi CRUD di base (e query) definiti e implementati .

Per definire metodi di accesso più specifici, Spring JPA supporta alcune opzioni:

  • definire semplicemente un nuovo metodo nell'interfaccia
  • fornire la query JPQL effettiva utilizzando l' annotazione @Query
  • utilizzare le specifiche più avanzate e il supporto Querydsl in Spring Data
  • definire query personalizzate tramite query denominate JPA

La terza opzione, le specifiche e il supporto Querydsl, è simile ai criteri JPA ma utilizza un'API più flessibile e conveniente. Ciò rende l'intera operazione molto più leggibile e riutilizzabile. I vantaggi di questa API diventeranno più evidenti quando si tratta di un gran numero di query fisse, poiché potremmo potenzialmente esprimerle in modo più conciso attraverso un numero inferiore di blocchi riutilizzabili.

Quest'ultima opzione ha lo svantaggio di coinvolgere XML o di gravare sulla classe di dominio con le query.

3.1. Query personalizzate automatiche

Quando Spring Data crea una nuova implementazione del repository , analizza tutti i metodi definiti dalle interfacce e cerca di generare automaticamente query dai nomi dei metodi . Sebbene abbia alcune limitazioni, è un modo molto potente ed elegante per definire nuovi metodi di accesso personalizzati con uno sforzo minimo.

Vediamo un esempio: se l'entità ha un campo nome (e i metodi getName e setName standard di Java Bean ), definiremo il metodo findByName nell'interfaccia DAO ; questo genererà automaticamente la query corretta:

public interface IFooDAO extends JpaRepository { Foo findByName(String name); }

Questo è un esempio relativamente semplice. Il meccanismo di creazione delle query supporta un insieme di parole chiave molto più ampio.

Nel caso in cui il parser non possa abbinare la proprietà con il campo dell'oggetto del dominio, vedremo la seguente eccezione:

java.lang.IllegalArgumentException: No property nam found for type class com.baeldung.spring.data.persistence.model.Foo

3.2. Query personalizzate manuali

Diamo ora un'occhiata a una query personalizzata che definiremo tramite l' annotazione @Query :

@Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)") Foo retrieveByName(@Param("name") String name);

Per un controllo ancora più dettagliato sulla creazione di query, come l'utilizzo di parametri denominati o la modifica di query esistenti, il riferimento è un buon punto di partenza.

4. Configurazione della transazione

L'implementazione effettiva del DAO gestito da Spring è effettivamente nascosta poiché non lavoriamo direttamente con esso. Tuttavia, questo è un abbastanza semplice implementazione - la SimpleJpaRepository - che definisce la semantica di transazione utilizzando le annotazioni .

Più esplicitamente, utilizza un'annotazione @Transactional di sola lettura a livello di classe, che viene quindi sovrascritta per i metodi non di sola lettura. Il resto della semantica della transazione è predefinita, ma questi possono essere facilmente sovrascritti manualmente per metodo.

4.1. La traduzione di eccezione è viva e vegeta

La domanda ora è: poiché Spring Data JPA non dipende dai vecchi modelli ORM ( JpaTemplate , HibernateTemplate ) e sono stati rimossi dalla Spring 5 - faremo ancora tradurre le nostre eccezioni JPA nella gerarchia DataAccessException di Spring ?

Of course, we are – exception translation is still enabled by the use of the @Repository annotation on the DAO. This annotation enables a Spring bean postprocessor to advise all @Repository beans with all the PersistenceExceptionTranslator instances found in the container, and provide exception translation just as before.

Let's verify exception translation with an integration test:

@Test(expected = DataIntegrityViolationException.class) public void givenFooHasNoName_whenInvalidEntityIsCreated_thenDataException() { service.create(new Foo()); }

Keep in mind that exception translation is done through proxies. In order for Spring to be able to create proxies around the DAO classes, these must not be declared final.

5. Spring Data JPA Repository Configuration

To activate the Spring JPA repository support we can use the @EnableJpaRepositories annotation and specify the package that contains the DAO interfaces:

@EnableJpaRepositories(basePackages = "com.baeldung.spring.data.persistence.repository") public class PersistenceConfig { ... }

We can do the same with an XML configuration:

6. Java or XML Configuration

We already discussed in great detail how to configure JPA in Spring in a previous article. Spring Data also takes advantage of Spring's support for the JPA @PersistenceContext annotation. It uses this to wire the EntityManager into the Spring factory bean responsible for creating the actual DAO implementations – JpaRepositoryFactoryBean.

In addition to the already discussed configuration, we also need to include the Spring Data XML Config – if we are using XML:

@Configuration @EnableTransactionManagement @ImportResource("classpath*:*springDataConfig.xml") public class PersistenceJPAConfig { ... }

7. Maven Dependency

In addition to the Maven configuration for JPA, like in a previous article, we'll add the spring-data-jpa dependency:

 org.springframework.data spring-data-jpa 2.2.7.RELEASE 

8. Using Spring Boot

We can also use the Spring Boot Starter Data JPA dependency that will automatically configure the DataSource for us.

We also need to make sure that the database we want to use is present in the classpath. In our example, we've added the H2 in-memory database:

 org.springframework.boot spring-boot-starter-data-jpa 2.2.6.RELEASE   com.h2database h2 1.4.200 

As a result, just by doing these dependencies, our application is up and running and we can use it for other database operations.

The explicit configuration for a standard Spring application is now included as part of Spring Boot auto-configuration.

We can, of course, modify the auto-configuration by adding our customized explicit configuration.

Spring Boot provides an easy way to do this using properties in the application.properties file:

spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 spring.datasource.username=sa spring.datasource.password=sa

In this example, we've changed the connection URL and credentials.

9. Conclusion

This article covered the configuration and implementation of the persistence layer with Spring 5, JPA 2, and Spring Data JPA (part of the Spring Data umbrella project), using both XML and Java-based configuration.

We discussed ways to define more advanced custom queries, as well as transactional semantics, and a configuration with the new jpa namespace. The final result is a new and elegant take on data access with Spring, with almost no actual implementation work.

L'implementazione di questo tutorial JPA di Spring Data può essere trovata nel progetto GitHub.