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
AccountRepositoryImpl
not:,AccountRepositoryCustomImpl
etc., 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.
QueryDslRepositorySupport
Tambié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*Impl
constructor.AccountRepositoryBasic
yAccountRepositoryCustom
estarán disponibles a través de un inyectadoAccountRepository
Su 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
Hobby
es 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
Impl
sufijo nos permite tener una solución limpia:@Repository
interfaz, por ejemploMyEntityRepository
, métodos Spring Data o métodos personalizados.MyEntityRepositoryImpl
(elImpl
sufijo 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
** (@Repository
no funcionará).MyEntityRepository
a través@Autowired
de 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:
Impl
clase están marcados como no utilizados por el compilador, de ahí la@SuppressWarnings("unused")
sugerencia.Impl
clase. (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