Eu estou olhando para o Spring Data JPA. Considere o exemplo abaixo, onde vou obter todas as funcionalidades de crud e finder funcionando por padrão e, se eu quiser personalizar um localizador, isso também poderá ser feito facilmente na própria interface.
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
@Query("<JPQ statement here>")
List<Account> findByCustomer(Customer customer);
}
Gostaria de saber como posso adicionar um método personalizado completo com sua implementação para o AccountRepository acima? Como é uma interface, não posso implementar o método lá.
fonte
AccountRepositoryImpl
not :,AccountRepositoryCustomImpl
etc. - é uma convenção de nomes muito estrita.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
Você também deve injetar o repositório via injeção de campo ou setter, em vez de injeção de construtor, caso contrário, ele não poderá criar o bean. Parece funcionar, mas a solução parece um pouco "suja", não tenho certeza se existem planos para melhorar como isso funciona da equipe do Spring Data.Além da resposta do axtavt , não se esqueça de que você pode injetar o Entity Manager em sua implementação personalizada, se você precisar criar suas consultas:
fonte
A resposta aceita funciona, mas tem três problemas:
AccountRepositoryImpl
. A documentação afirma claramente que deve ser chamadaAccountRepositoryCustomImpl
, o nome da interface personalizada maisImpl
@Autowired
, que é considerada uma má práticaEu encontrei uma maneira de torná-lo perfeito, embora não sem o uso de outro recurso não documentado do Spring Data:
fonte
accountRepositoryBasic
). Caso contrário, a primavera reclamou da existência de duas opções de feijão para injeção no meu*Impl
construtor.AccountRepositoryBasic
eAccountRepositoryCustom
estarão disponíveis por meio de uma injeçãoAccountRepository
O uso é limitado, mas para métodos personalizados simples, você pode usar métodos de interface padrão , como:
EDITAR:
Na Primavera deste ano tutorial está escrito:
Portanto, é possível apenas declarar um método como:
e se o objeto
Hobby
for uma propriedade do Cliente, o Spring definirá automaticamente o método para você.fonte
Estou usando o código a seguir para acessar os métodos de localização gerados da minha implementação personalizada. A implementação da fábrica de beans evita problemas de criação circular de beans.
fonte
Conforme especificado na funcionalidade documentada , o
Impl
sufixo nos permite ter uma solução limpa:@Repository
interface, digamosMyEntityRepository
, métodos Spring Data ou métodos personalizadosMyEntityRepositoryImpl
(oImpl
sufixo é a mágica) em qualquer lugar (nem precisa estar no mesmo pacote) que implemente apenas os métodos personalizados e anote essa classe com@Component
** (@Repository
não funcionará).MyEntityRepository
via@Autowired
para uso nos métodos personalizados.Exemplo:
Classe de entidade:
Interface do repositório:
Bean de implementação de métodos customizados:
As pequenas desvantagens que identifiquei são:
Impl
classe são marcados como não utilizados pelo compilador, portanto, o@SuppressWarnings("unused")
sugestão.Impl
classe. (Enquanto na implementação regular das interfaces de fragmento, os documentos sugerem que você pode ter muitos.)fonte
MyEntityRepository
, não o*Impl
.Se você deseja realizar operações mais sofisticadas, pode precisar de acesso aos componentes internos do Spring Data. Nesse caso, o seguinte funciona (como minha solução provisória para o DATAJPA-422 ):
fonte
Considerando o seu snippet de código, observe que você só pode passar objetos nativos para o método findBy ###, digamos que deseja carregar uma lista de contas que pertencem a determinados clientes, uma solução é fazer isso,
Faça com que o nome da tabela a ser consultada seja o mesmo que a classe Entity. Para outras implementações, dê uma olhada neste
fonte
Há outra questão a ser considerada aqui. Algumas pessoas esperam que a adição de método personalizado ao seu repositório os exponha automaticamente como serviços REST no link '/ search'. Infelizmente, este não é o caso. A primavera não suporta isso atualmente.
Esse é o recurso "por design", o restante dos dados da primavera verifica explicitamente se o método é um método personalizado e não o expõe como um link de pesquisa REST:
Este é um qoute de Oliver Gierke:
Para mais detalhes, consulte este problema: https://jira.spring.io/browse/DATAREST-206
fonte
@RestResource(path = "myQueryMethod")
anotação ao método. A citação acima está apenas afirmando que o Spring não sabe como você deseja que ele seja mapeado (por exemplo, GET vs POST etc.), portanto, cabe a você especificá-lo através da anotação.Incluindo comportamento personalizado em todos os repositórios:
Para adicionar um comportamento personalizado a todos os repositórios, primeiro adicione uma interface intermediária para declarar o comportamento compartilhado.
Agora, suas interfaces de repositório individuais estenderão essa interface intermediária em vez da interface de repositório para incluir a funcionalidade declarada.
Em seguida, crie uma implementação da interface intermediária que estenda a classe base do repositório específico da tecnologia de persistência. Essa classe atuará como uma classe base personalizada para os proxies do repositório.
Repositórios de Dados Spring Parte I. Referência
fonte
Eu estendo o SimpleJpaRepository:
e adiciona essa classe a @EnableJpaRepositoryries repositoryBaseClass.
fonte