Jak dodać niestandardową metodę do Spring Data JPA
[[1]}Szukam Spring Data JPA. Rozważ poniższy przykład, w którym wszystkie funkcje crud i Findera będą działać domyślnie, a jeśli chcę dostosować finder, to można to łatwo zrobić również w samym interfejsie.
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
@Query("<JPQ statement here>")
List<Account> findByCustomer(Customer customer);
}
Chciałbym się dowiedzieć, jak Mogę dodać kompletną metodę niestandardową z jej implementacją dla powyższego AccountRepository? Ponieważ jest to interfejs, nie mogę zaimplementować tej metody.
8 answers
Musisz utworzyć osobny interfejs dla własnych metod:
public interface AccountRepository
extends JpaRepository<Account, Long>, AccountRepositoryCustom { ... }
public interface AccountRepositoryCustom {
public void customMethod();
}
I podaj klasę implementacji dla tego interfejsu:
public class AccountRepositoryImpl implements AccountRepositoryCustom {
@Autowired
AccountRepository accountRepository; /* Optional - if you need it */
public void customMethod() { ... }
}
Zobacz też:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-05 19:07:38
Oprócz odpowiedzi axtavt , nie zapomnij, że możesz wprowadzić Entity Manager w swojej niestandardowej implementacji, jeśli potrzebujesz go do budowania zapytań:
public class AccountRepositoryImpl implements AccountRepositoryCustom {
@PersistenceContext
private EntityManager em;
public void customMethod() {
...
em.createQuery(yourCriteria);
...
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:39
Jest to ograniczone w użyciu, ale dla prostych metod niestandardowych można użyć domyślnych metod interfejsu, takich jak:
import demo.database.Customer;
import org.springframework.data.repository.CrudRepository;
public interface CustomerService extends CrudRepository<Customer, Long> {
default void addSomeCustomers() {
Customer[] customers = {
new Customer("Józef", "Nowak", "[email protected]", 679856885, "Rzeszów", "Podkarpackie", "35-061", "Zamknięta 12"),
new Customer("Adrian", "Mularczyk", "[email protected]", 867569344, "Krosno", "Podkarpackie", "32-442", "Hynka 3/16"),
new Customer("Kazimierz", "Dejna", "[email protected]", 996435876, "Jarosław", "Podkarpackie", "25-122", "Korotyńskiego 11"),
new Customer("Celina", "Dykiel", "[email protected]", 947845734, "Żywiec", "Śląskie", "54-333", "Polna 29")
};
for (Customer customer : customers) {
save(customer);
}
}
}
EDIT:
W tej wiosny tutorial jest napisany:
Spring Data JPA umożliwia również definiowanie innych metod zapytań za pomocą po prostu deklarując swój podpis metody.
Więc możliwe jest nawet zadeklarowanie metody w stylu:
Customer findByHobby(Hobby personHobby);
I jeśli obiekt Hobby
jest własnością Klienta, To Spring automatycznie zdefiniuj metodę dla siebie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-24 21:27:48
Używam poniższego kodu, aby uzyskać dostęp do wygenerowanych metod wyszukiwania z mojej niestandardowej implementacji. Wdrożenie w fabryce fasoli zapobiega problemom z tworzeniem fasoli okrągłej.
public class MyRepositoryImpl implements MyRepositoryExtensions, BeanFactoryAware {
private BrandRepository myRepository;
public MyBean findOne(int first, int second) {
return myRepository.findOne(new Id(first, second));
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
myRepository = beanFactory.getBean(MyRepository.class);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-24 05:13:47
Biorąc pod uwagę Twój fragment kodu, pamiętaj, że możesz przekazać tylko natywne obiekty do metody findBy###, powiedzmy, że chcesz załadować listę kont, które należą do niektórych klientów, jednym z rozwiązań jest to,
@Query("Select a from Account a where a."#nameoffield"=?1")
List<Account> findByCustomer(String "#nameoffield");
Niech sue nazwa tabeli, która ma być zapytana, będzie nazwą klasy encji. Aby uzyskać dalsze implementacje, zapoznaj się z this
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-18 08:48:16
Jeśli chcesz być w stanie wykonywać bardziej zaawansowane operacje, możesz potrzebować dostępu do wewnętrznych danych Spring Data, w takim przypadku następujące działania (jako moje tymczasowe rozwiązanie do DATAJPA-422):
public class AccountRepositoryImpl implements AccountRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
private JpaEntityInformation<Account, ?> entityInformation;
@PostConstruct
public void postConstruct() {
this.entityInformation = JpaEntityInformationSupport.getMetadata(Account.class, entityManager);
}
@Override
@Transactional
public Account saveWithReferenceToOrganisation(Account entity, long referralId) {
entity.setOrganisation(entityManager.getReference(Organisation.class, organisationId));
return save(entity);
}
private Account save(Account entity) {
// save in same way as SimpleJpaRepository
if (entityInformation.isNew(entity)) {
entityManager.persist(entity);
return entity;
} else {
return entityManager.merge(entity);
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-31 15:16:29
Jest jeszcze jedna kwestia, którą należy rozważyć. Niektórzy oczekują, że dodanie niestandardowej metody do repozytorium automatycznie wyświetli je jako usługi REST pod linkiem' / search'. Niestety tak nie jest. Wiosna tego obecnie nie wspiera.
Jest to funkcja 'by design', Spring data rest jawnie sprawdza, czy metoda jest metodą niestandardową i nie wyświetla jej jako link wyszukiwania REST:
private boolean isQueryMethodCandidate(Method method) {
return isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method);
}
To jest qoute Olivera Gierke:
To jest przez design. Niestandardowe metody repozytorium nie są metodami zapytań, jak mogą skutecznie realizować każde zachowanie. Tak więc obecnie niemożliwe jest dla nas podjęcie decyzji o metodzie HTTP, aby wyeksponować metodę pod. POST byłby najbezpieczniejszą opcją, ale nie jest to zgodne z ogólne metody zapytań (które otrzymują GET).
Więcej szczegółów znajdziesz w tym numerze: https://jira.spring.io/browse/DATAREST-206
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-21 08:35:03
Przyjęta odpowiedź działa, ale ma trzy problemy:
- używa nieudokumentowanej funkcji Spring Data podczas nazywania niestandardowej implementacji jako
AccountRepositoryImpl
. Dokumentacja wyraźnie stwierdza, że musi być wywołanaAccountRepositoryCustomImpl
, niestandardowa nazwa interfejsu plusImpl
- nie można używać constructor injection, tylko
@Autowired
, które są uważane za złe praktyki - wewnątrz niestandardowej implementacji masz kolistą zależność (dlatego nie możesz użyć konstruktora wstrzyknięcie).
Znalazłem sposób, aby uczynić go idealnym, choć nie bez użycia innej nieudokumentowanej funkcji danych źródłowych: {]}
public interface AccountRepository extends AccountRepositoryBasic,
AccountRepositoryCustom
{
}
public interface AccountRepositoryBasic extends JpaRepository<Account, Long>
{
// standard Spring Data methods, like findByLogin
}
public interface AccountRepositoryCustom
{
public void customMethod();
}
public class AccountRepositoryCustomImpl implements AccountRepositoryCustom
{
private final AccountRepositoryBasic accountRepositoryBasic;
// constructor-based injection
public AccountRepositoryCustomImpl(
AccountRepositoryBasic accountRepositoryBasic)
{
this.accountRepositoryBasic = accountRepositoryBasic;
}
public void customMethod()
{
// we can call all basic Spring Data methods using
// accountRepositoryBasic
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-30 22:38:03