Estoy investigando Spring Data JPA. Considere el ejemplo a continuación, donde conseguiré que todas las funciones de búsqueda y búsqueda funcionen de manera predeterminada y si deseo personalizar un buscador, eso también se puede hacer fácilmente en la interfaz.
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
@Query("<JPQ statement here>")
List<Account> findByCustomer(Customer customer);
}
Me gustaría saber cómo puedo agregar un método personalizado completo con su implementación para el AccountRepository anterior. Como es una interfaz, no puedo implementar el método allí.
fuente

AccountRepositoryImplnot:,AccountRepositoryCustomImpletc., es una convención de nomenclatura muy estricta.Error creating bean with name 'accountRepositoryImpl': Bean with name 'accountRepositoryImpl' has been injected into other beans [accountRepository] in its raw version as part of a circular reference, but has eventually been wrapped.QueryDslRepositorySupportTambién debe inyectar el repositorio a través de la inyección de campo o setter en lugar de la inyección del constructor, de lo contrario no podrá crear el bean. Parece que funciona, pero la solución se siente un poco 'sucia', no estoy seguro de si hay planes para mejorar cómo funciona esto por parte del equipo de Spring Data.Además de la respuesta de axtavt , no olvide que puede inyectar Entity Manager en su implementación personalizada si lo necesita para generar sus consultas:
fuente
La respuesta aceptada funciona, pero tiene tres problemas:
AccountRepositoryImpl. La documentación indica claramente que debe llamarseAccountRepositoryCustomImpl, el nombre de la interfaz personalizada másImpl@Autowired, que se consideran una mala prácticaEncontré una manera de hacerlo perfecto, aunque no sin usar otra función Spring Data indocumentada:
fuente
accountRepositoryBasic). De lo contrario, Spring se quejó de que había 2 opciones de frijol para inyectar en mi*Implconstructor.AccountRepositoryBasicyAccountRepositoryCustomestarán disponibles a través de un inyectadoAccountRepositorySu uso es limitado, pero para métodos personalizados simples puede usar métodos de interfaz predeterminados como:
EDITAR:
En este tutorial de primavera está escrito:
Por lo tanto, incluso es posible declarar un método como:
y si el objeto
Hobbyes propiedad del Cliente, Spring definirá automáticamente el método para usted.fuente
Estoy usando el siguiente código para acceder a los métodos de búsqueda generados desde mi implementación personalizada. Obtener la implementación a través de la fábrica de beans evita problemas de creación de beans circulares.
fuente
Como se especifica en la funcionalidad documentada , el
Implsufijo nos permite tener una solución limpia:@Repositoryinterfaz, por ejemploMyEntityRepository, métodos Spring Data o métodos personalizados.MyEntityRepositoryImpl(elImplsufijo es la magia) en cualquier lugar (ni siquiera necesita estar en el mismo paquete) que implemente solo los métodos personalizados y anote dicha clase con@Component** (@Repositoryno funcionará).MyEntityRepositorya través@Autowiredde su uso en los métodos personalizados.Ejemplo:
Clase de entidad:
Interfaz de repositorio:
Bean de implementación de métodos personalizados:
Los pequeños inconvenientes que identifiqué son:
Implclase están marcados como no utilizados por el compilador, de ahí la@SuppressWarnings("unused")sugerencia.Implclase. (Mientras que en la implementación de interfaces de fragmentos regulares, los documentos sugieren que podría tener muchos).fuente
MyEntityRepository, no el*Impl.Si desea poder realizar operaciones más sofisticadas, es posible que necesite acceso a las partes internas de Spring Data, en cuyo caso lo siguiente funciona (como mi solución provisional para DATAJPA-422 ):
fuente
Teniendo en cuenta su fragmento de código, tenga en cuenta que solo puede pasar objetos nativos al método findBy ###, digamos que desea cargar una lista de cuentas que pertenecen a ciertos clientes, una solución es hacer esto,
Hacer demandar el nombre de la tabla a consultar es la misma clase de entidad. Para otras implementaciones, échale un vistazo a esto
fuente
Hay otro problema a considerar aquí. Algunas personas esperan que agregar un método personalizado a su repositorio los expondrá automáticamente como servicios REST en el enlace '/ buscar'. Desafortunadamente, este no es el caso. Spring no es compatible con eso actualmente.
Esta es la característica 'por diseño', el resto de datos de primavera verifica explícitamente si el método es un método personalizado y no lo expone como un enlace de búsqueda REST:
Esta es una qoute de Oliver Gierke:
Para obtener más detalles, consulte este problema: https://jira.spring.io/browse/DATAREST-206
fuente
@RestResource(path = "myQueryMethod")anotación al método. La cita anterior solo indica que Spring no sabe cómo desea que se asigne (es decir, GET vs POST, etc.), por lo que depende de usted especificarlo a través de la anotación.Agregar un comportamiento personalizado a todos los repositorios:
Para agregar un comportamiento personalizado a todos los repositorios, primero agregue una interfaz intermedia para declarar el comportamiento compartido.
Ahora sus interfaces de repositorio individuales ampliarán esta interfaz intermedia en lugar de la interfaz de repositorio para incluir la funcionalidad declarada.
A continuación, cree una implementación de la interfaz intermedia que amplíe la clase base de repositorio específico de tecnología de persistencia. Esta clase actuará como una clase base personalizada para los servidores proxy del repositorio.
Spring Data Repositories Parte I. Referencia
fuente
Extiendo el SimpleJpaRepository:
y agrega esta clase a @EnableJpaRepositoryries repositoryBaseClass.
fuente