Ich beschäftige mich mit Spring Data JPA. Betrachten Sie das folgende Beispiel, in dem standardmäßig alle Funktionen für Rohöl und Finder funktionieren. Wenn ich einen Finder anpassen möchte, kann dies auch problemlos in der Benutzeroberfläche selbst durchgeführt werden.
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
@Query("<JPQ statement here>")
List<Account> findByCustomer(Customer customer);
}
Ich möchte wissen, wie ich eine vollständige benutzerdefinierte Methode mit ihrer Implementierung für das oben genannte AccountRepository hinzufügen kann. Da es sich um eine Schnittstelle handelt, kann ich die Methode dort nicht implementieren.
quelle
AccountRepositoryImpl
nicht:AccountRepositoryCustomImpl
usw. - Dies ist eine sehr strenge Namenskonvention.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
Sie müssen das Repository auch über eine Feld- oder Setter-Injektion anstelle einer Konstruktor-Injektion injizieren, da es sonst nicht in der Lage ist, die Bean zu erstellen. Es scheint zu funktionieren, aber die Lösung fühlt sich ein bisschen "schmutzig" an. Ich bin mir nicht sicher, ob es Pläne gibt, die Funktionsweise des Spring Data-Teams zu verbessern.Vergessen Sie nicht, dass Sie neben der Antwort von axtavt auch Entity Manager in Ihre benutzerdefinierte Implementierung einfügen können, wenn Sie ihn zum Erstellen Ihrer Abfragen benötigen:
quelle
Die akzeptierte Antwort funktioniert, hat aber drei Probleme:
AccountRepositoryImpl
. In der Dokumentation ist eindeutig angegeben, dassAccountRepositoryCustomImpl
der Name der benutzerdefinierten Schnittstelle plus aufgerufen werden mussImpl
@Autowired
die als schlechte Praxis angesehen wirdIch habe einen Weg gefunden, es perfekt zu machen, allerdings nicht ohne eine andere undokumentierte Spring Data-Funktion zu verwenden:
quelle
accountRepositoryBasic
). Ansonsten beschwerte sich Spring darüber, dass es 2 Bohnen zur Injektion in meinen*Impl
Konstruktor gibt.AccountRepositoryBasic
undAccountRepositoryCustom
wird über eine injizierteAccountRepository
Dies ist in der Verwendung begrenzt, aber für einfache benutzerdefinierte Methoden können Sie Standardschnittstellenmethoden verwenden, wie:
BEARBEITEN:
In diesem Frühjahrstutorial steht geschrieben:
Es ist also sogar möglich, eine Methode wie folgt zu deklarieren:
Wenn das Objekt
Hobby
Eigentum des Kunden ist, definiert Spring automatisch die Methode für Sie.quelle
Ich verwende den folgenden Code, um auf generierte Suchmethoden aus meiner benutzerdefinierten Implementierung zuzugreifen. Durch die Implementierung durch die Bean Factory werden Probleme bei der Erstellung von Circular Bean vermieden.
quelle
Wie in der dokumentierten Funktionalität angegeben ,
Impl
ermöglicht uns das Suffix eine saubere Lösung:@Repository
Schnittstelle, sagen wirMyEntityRepository
entweder Spring Data-Methoden oder benutzerdefinierte MethodenMyEntityRepositoryImpl
(dasImpl
Suffix ist die Magie) (muss sich nicht einmal im selben Paket befinden), die nur die benutzerdefinierten Methoden implementiert, und kommentieren Sie diese Klasse mit@Component
** ( funktioniert@Repository
nicht ).MyEntityRepository
über@Autowired
zur Verwendung in den benutzerdefinierten Methoden injizieren .Beispiel:
Entitätsklasse:
Repository-Schnittstelle:
Implementierungs-Bean für benutzerdefinierte Methoden:
Die kleinen Nachteile, die ich identifiziert habe, sind:
Impl
Klasse werden vom Compiler als nicht verwendet markiert, daher der@SuppressWarnings("unused")
Vorschlag.Impl
Klasse. (Während in der regulären Implementierung der Fragmentschnittstellen die Dokumente vorschlagen, dass Sie viele haben könnten.)quelle
MyEntityRepository
, nicht die*Impl
.Wenn Sie komplexere Vorgänge ausführen möchten, benötigen Sie möglicherweise Zugriff auf die Interna von Spring Data. In diesem Fall funktioniert Folgendes (als meine Zwischenlösung für DATAJPA-422 ):
quelle
Beachten Sie in Anbetracht Ihres Code-Snippets, dass Sie nur native Objekte an die findBy ### -Methode übergeben können. Nehmen wir an, Sie möchten eine Liste von Konten laden, die bestimmten Kunden gehören. Eine Lösung besteht darin, dies zu tun.
Stellen Sie sicher, dass der Name der abzufragenden Tabelle derselbe ist wie die Entitätsklasse. Für weitere Implementierungen schauen Sie sich dies bitte an
quelle
Es gibt noch ein weiteres Problem, das hier berücksichtigt werden muss. Einige Leute erwarten, dass das Hinzufügen einer benutzerdefinierten Methode zu Ihrem Repository sie automatisch als REST-Services unter dem Link '/ search' verfügbar macht. Dies ist leider nicht der Fall. Der Frühling unterstützt das derzeit nicht.
Dies ist eine 'by Design'-Funktion. Spring Data Rest prüft explizit, ob es sich bei der Methode um eine benutzerdefinierte Methode handelt, und macht sie nicht als REST-Suchlink verfügbar:
Dies ist eine Frage von Oliver Gierke:
Weitere Informationen finden Sie in diesem Problem: https://jira.spring.io/browse/DATAREST-206
quelle
@RestResource(path = "myQueryMethod")
der Methode einfach die Anmerkung hinzufügen . Das obige Zitat besagt lediglich, dass Spring nicht weiß, wie Sie es zuordnen möchten (dh GET vs POST usw.). Es liegt also an Ihnen, es über die Anmerkung anzugeben.Hinzufügen eines benutzerdefinierten Verhaltens zu allen Repositorys:
Um allen Repositorys benutzerdefiniertes Verhalten hinzuzufügen, fügen Sie zunächst eine Zwischenschnittstelle hinzu, um das freigegebene Verhalten zu deklarieren.
Jetzt erweitern Ihre individuellen Repository-Schnittstellen diese Zwischenschnittstelle anstelle der Repository-Schnittstelle um die deklarierte Funktionalität.
Erstellen Sie als Nächstes eine Implementierung der Zwischenschnittstelle, die die für die Persistenztechnologie spezifische Repository-Basisklasse erweitert. Diese Klasse fungiert dann als benutzerdefinierte Basisklasse für die Repository-Proxys.
Spring Data Repositories Teil I. Referenz
quelle
Ich erweitere das SimpleJpaRepository:
und fügt diese Klasse zu @EnableJpaRepositoryries repositoryBaseClass hinzu.
quelle