En el artículo describiré el uso de Spring Data.
Spring Data es un mecanismo adicional conveniente para interactuar con entidades de bases de datos, organizarlas en un repositorio, recuperar datos, cambiar, en algunos casos, para esto será suficiente declarar una interfaz y un método en él, sin implementación.
Contenido:
- Repositorio de primavera
- Solicitar métodos del nombre del método
- Configuración y configuración
- Procesamiento de parámetros especiales
- Implementaciones de repositorio personalizadas
- Repositorio base personalizado
- Métodos de consulta - Consulta
1. Depósito de primavera
El concepto básico en Spring Data es el repositorio. Estas son varias interfaces que utilizan la entidad JPA para interactuar con ella. Entonces, por ejemplo, una interfaz
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID>
proporciona operaciones básicas para buscar, guardar y eliminar datos (operaciones CRUD)
T save(T entity); Optional findById(ID primaryKey); void delete(T entity);
y otras operaciones.
Hay otras abstracciones, como PagingAndSortingRepository.
Es decir Si la lista que proporciona la interfaz es suficiente para interactuar con la entidad, puede expandir directamente la interfaz base de su entidad, complementarla con sus métodos de consulta y realizar operaciones. Ahora mostraré brevemente los pasos necesarios para el caso más simple (sin distraerme con la configuración, ORM, base de datos).
1. Crear una entidad
@Entity @Table(name = "EMPLOYEES") public class Employees { private Long employeeId; private String firstName; private String lastName; private String email;
2. Heredado de una de las interfaces de Spring Data, por ejemplo de CrudRepository
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>
3. Use en el cliente (servicio) una nueva interfaz para operaciones de datos
@Service public class EmployeesDataService { @Autowired private CustomizedEmployeesCrudRepository employeesCrudRepository; @Transactional public void testEmployeesCrudRepository() { Optional<Employees> employeesOptional = employeesCrudRepository.findById(127L);
Aquí utilicé el método
findById listo para
usar . Es decir de manera rápida y fácil, sin implementación, obtenemos una lista de operaciones preparada de CrudRepository:
S save(S var1); Iterable<S> saveAll(Iterable<S> var1); Optional<T> findById(ID var1); boolean existsById(ID var1); Iterable<T> findAll(); Iterable<T> findAllById(Iterable<ID> var1); long count(); void deleteById(ID var1); void delete(T var1); void deleteAll(Iterable<? extends T> var1); void deleteAll();
Está claro que esta lista probablemente no sea suficiente para interactuar con la entidad, y aquí puede expandir su interfaz con métodos de consulta adicionales.
2. Consultar métodos desde el nombre del método
Las solicitudes a la entidad se pueden construir directamente desde el nombre del método. Para hacer esto, se usan los prefijos find ... By, read ... By, query ... By, count ... By y get ... By, más allá del prefijo del método, comienza a analizar el resto. La oración introductoria puede contener expresiones adicionales, por ejemplo, Distinct. A continuación, el primer By actúa como un delimitador para indicar el inicio de los criterios reales. Puede definir condiciones para las propiedades de la entidad y combinarlas con And y Or. Ejemplos
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long> {
La documentación define la lista completa y las reglas para escribir el método. El resultado puede ser una entidad T, Opcional, Lista, Secuencia. En un entorno de desarrollo, como Idea, hay una pista para escribir métodos de consulta.

Es suficiente definir un método de esta manera, sin implementación, y Spring preparará una solicitud para la entidad.
@SpringBootTest public class DemoSpringDataApplicationTests { @Autowired private CustomizedEmployeesCrudRepository employeesCrudRepository; @Test @Transactional public void testFindByFirstNameAndLastName() { Optional<Employees> employeesOptional = employeesCrudRepository.findByFirstNameAndLastName("Alex", "Ivanov");
3. Configuración y configuración
Todo el proyecto está disponible en github
github DemoSpringDataAquí solo tocaré algunas características.
Los beans TransactionManager, dataSource y entityManagerFactory se definen en context.xml. Es importante indicar en él también
<jpa:repositories base-package="com.example.demoSpringData.repositories"/>
ruta donde se definen los repositorios.
EntityManagerFactory está configurado para funcionar con Hibernate ORM y, a su vez, está con la base de datos Oracle XE, aquí son posibles otras opciones, en context.xml todo esto es visible. El archivo pom tiene todas las dependencias.
4. Procesamiento especial de parámetros.
En los métodos de consulta, en sus parámetros, puede usar parámetros especiales Pageable, Ordenar, así como las restricciones Top y First.
Por ejemplo, de esta manera, puede tomar la segunda página (índice con -0), el tamaño de tres elementos y ordenar por nombre, después de especificar el parámetro Pageable en el método del repositorio, los criterios del nombre del método también se utilizarán: "Buscar por nombre comenzando con%„
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long> { List<Employees> findByFirstNameStartsWith(String firstNameStartsWith, Pageable page);
5. Implementaciones personalizadas para el repositorio
Suponga que necesita un método en el repositorio que no se puede describir con el nombre del método, luego puede implementarlo utilizando su propia interfaz y su clase de implementación. En el siguiente ejemplo, agregaré al repositorio un método para obtener empleados con el pago máximo.
Declarar interfaz
public interface CustomizedEmployees<T> { List<T> getEmployeesMaxSalary(); }
Implementa la interfaz. Usando HQL (SQL) obtengo empleados con el pago máximo, otras implementaciones son posibles.
public class CustomizedEmployeesImpl implements CustomizedEmployees { @PersistenceContext private EntityManager em; @Override public List getEmployeesMaxSalary() { return em.createQuery("from Employees where salary = (select max(salary) from Employees )", Employees.class) .getResultList(); } }
Y también expandiendo Crud Repository Employees con CustomizedEmployees.
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>, CustomizedEmployees<Employees>
Hay una característica importante aquí. La interfaz de implementación de la clase debe finalizar (postfix) en
Impl , o en la configuración que necesita para poner su postfix
<repositories base-package="com.repository" repository-impl-postfix="MyPostfix" />
Comprobación del funcionamiento de este método a través del repositorio
public class DemoSpringDataApplicationTests { @Autowired private CustomizedEmployeesCrudRepository employeesCrudRepository; @Test @Transactional public void testMaxSalaryEmployees() { List<Employees> employees = employeesCrudRepository.getEmployeesMaxSalary(); employees.stream() .forEach(e -> System.out.println(e.getFirstName() + " " + e.getLastName() + " " + e.getSalary())); }
Otro caso cuando es necesario cambiar el comportamiento de un método existente en la interfaz de Spring, por ejemplo, eliminar en CrudRepository, necesito que en lugar de eliminar de la base de datos, se establezca un signo de eliminación. La técnica es exactamente la misma. A continuación se muestra un ejemplo:
public interface CustomizedEmployees<T> { void delete(T entity);
Ahora, si llama a
delete en employeeCrudRepository, el objeto solo se marcará como eliminado.
6. Repositorio base de usuario
En el ejemplo anterior, mostré cómo redefinir el repositorio de eliminación de una entidad en Crud, pero si necesita hacer esto para todas las entidades del proyecto, haga que su propia interfaz no sea tan buena para cada ... entonces en Spring data puede configurar su repositorio base. Para hacer esto:
Se declara una interfaz y en ella un método de anulación (o común a todas las entidades del proyecto). Aquí, para todas mis entidades, introduje mi interfaz
BaseEntity (esto no es necesario), para la conveniencia de llamar a métodos comunes, sus métodos coinciden con los métodos de la entidad.
public interface BaseEntity { Boolean getDeleted(); void setDeleted(Boolean deleted); }
En la configuración, debe especificar este repositorio base, será común a todos los repositorios de proyectos.
<jpa:repositories base-package="com.example.demoSpringData.repositories" base-class="com.example.demoSpringData.BaseRepositoryImpl"/>
Ahora el repositorio de empleados (y otros) se debe expandir desde BaseRepository y ya usarlo en el cliente.
public interface EmployeesBaseRepository extends BaseRepository <Employees, Long> {
Comprobando EmployeesBaseRepository
public class DemoSpringDataApplicationTests { @Resource private EmployeesBaseRepository employeesBaseRepository; @Test @Transactional @Commit public void testBaseRepository() { Employees employees = new Employees(); employees.setLastName("Ivanov");
Ahora, como antes, el objeto se marcará como eliminado, y esto se realizará para todas las entidades que extiendan la interfaz BaseRepository. En el ejemplo, se aplicó el método de búsqueda -
Consulta por ejemplo (QBE) , no lo describiré aquí, el ejemplo muestra lo que hace, simple y conveniente.
Anteriormente, escribí que si necesita un método específico o su implementación, que no se puede describir con el nombre del método, esto se puede hacer a través de una interfaz personalizada (CustomizedEmployees) y realizar una implementación de cálculo. Y puede ir hacia otro lado, indicando la consulta (HQL o SQL), cómo calcular esta función.
Para mi ejemplo con getEmployeesMaxSalary, esta opción de implementación es aún más simple. Lo complicaré con el parámetro de ingreso salarial. Es decir es suficiente declarar el método de cálculo y la solicitud en la interfaz.
@Repository public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>, CustomizedEmployees<Employees> { @Query("select e from Employees e where e.salary > :salary") List<Employees> findEmployeesWithMoreThanSalary(@Param("salary") Long salary, Sort sort);
Comprobando
@Test @Transactional public void testFindEmployeesWithMoreThanSalary() { List<Employees> employees = employeesCrudRepository.findEmployeesWithMoreThanSalary(10000L, Sort.by("lastName"));
Solo mencionaré que puede haber solicitudes de modificación, para esto se les agrega una anotación
@Modifying adicional
@Modifying @Query("update Employees e set e.firstName = ?1 where e.employeeId = ?2") int setFirstnameFor(String firstName, String employeeId);
Otra de las grandes características de las anotaciones de
consulta es la sustitución del tipo de dominio de entidad en la consulta utilizando la plantilla
# {# entityName} , a través de expresiones SpEL.
Entonces, por ejemplo, en mi ejemplo hipotético, cuando necesito tener el signo "eliminado" para todas las entidades, haré una interfaz básica con un método para obtener una lista de objetos con el signo "eliminado" o "activo"
@NoRepositoryBean public interface ParentEntityRepository<T> extends Repository<T, Long> { @Query("select t from #{#entityName} t where t.deleted = ?1") List<T> findMarked(Boolean deleted); }
Además, todos los repositorios para entidades pueden extenderse desde él. Las interfaces que no son repositorios, pero se encuentran en la carpeta de configuración del "paquete base", anotan @NoRepositoryBean.
Depósito de empleados
@Repository public interface EmployeesEntityRepository extends ParentEntityRepository <Employees> { }
Ahora, cuando se ejecuta la solicitud, el nombre de la entidad
T será sustituido en el cuerpo de la solicitud por un repositorio específico que extenderá el ParentEntityRepository, en este caso Empleados.
Cheque
@SpringBootTest public class DemoSpringDataApplicationTests { @Autowired private EmployeesEntityRepository employeesEntityRepository; @Test @Transactional public void testEntityName() { List<Employees> employeesMarked = employeesEntityRepository.findMarked(true);
Materiales
Spring Data JPA - Documentación de referenciaProyecto en github .