Einführung in Spring Data Neo4j

1. Übersicht

Dieser Artikel ist eine Einführung in Spring Data Neo4j , die beliebte Grafikdatenbank.

Spring Data Neo4j ermöglicht die POJO-basierte Entwicklung für die Neo4j Graph-Datenbank und verwendet bekannte Spring-Konzepte wie Vorlagenklassen für die Verwendung der Kern-API und bietet ein auf Anmerkungen basierendes Programmiermodell.

Außerdem wissen viele Entwickler nicht wirklich, ob Neo4j tatsächlich gut zu ihren spezifischen Anforderungen passt. Hier ist eine solide Übersicht über Stackoverflow, in der erläutert wird, warum Neo4j verwendet wird und welche Vor- und Nachteile es gibt.

2. Maven-Abhängigkeiten

Beginnen wir mit der Deklaration der Spring Data Neo4j-Abhängigkeiten in der Datei pom.xml. Die unten genannten Federmodule werden auch für Spring Data Neo4j benötigt:

 org.springframework.data spring-data-neo4j 5.0.1.RELEASE   org.neo4j neo4j-ogm-test 3.1.2 test 

Diese Abhängigkeiten umfassen auch die erforderlichen Module zum Testen.

Beachten Sie, dass die letzte Abhängigkeit als "Test" festgelegt ist. Beachten Sie jedoch auch, dass in einer realen Anwendungsentwicklung mit größerer Wahrscheinlichkeit ein vollständiger Neo4J-Server ausgeführt wird.

Wenn wir den eingebetteten Server verwenden möchten, müssen wir auch die Abhängigkeit hinzufügen:

 org.neo4j neo4j-ogm-embedded-driver 3.1.2 

Die Abhängigkeiten von spring-data-neo4j, neo4j-ogm-test und neo4j-ogm-embedded-driver sind in Maven Central verfügbar.

3. Neo4Jj-Konfiguration

Die Neo4j-Konfiguration ist sehr einfach und definiert die Verbindungseinstellung für die Anwendung, um eine Verbindung zum Server herzustellen. Ähnlich wie bei den meisten anderen Federdatenmodulen ist dies eine Federkonfiguration, die als XML- oder Java-Konfiguration definiert werden kann.

In diesem Tutorial verwenden wir nur die Java-basierte Konfiguration:

public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL") : "//neo4j:[email protected]:7474"; @Bean public org.neo4j.ogm.config.Configuration getConfiguration() { return new Builder().uri(URL).build(); } @Bean public SessionFactory getSessionFactory() { return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); } @Bean public Neo4jTransactionManager transactionManager() { return new Neo4jTransactionManager(getSessionFactory()); }

Wie oben erwähnt, ist die Konfiguration einfach und enthält nur zwei Einstellungen. Erstens verweist die SessionFactory auf die Modelle, die wir zur Darstellung der Datenobjekte erstellt haben. Anschließend werden die Verbindungseigenschaften mit den Serverendpunkten und den Zugriffsdaten angegeben.

Neo4j leitet die Treiberklasse basierend auf dem Protokoll der URI ab, in unserem Fall "http".

Beachten Sie, dass in diesem Beispiel die verbindungsbezogenen Eigenschaften direkt für den Server konfiguriert werden. In einer Produktionsanwendung sollten diese jedoch ordnungsgemäß externalisiert werden und Teil der Standardkonfiguration des Projekts sein.

4. Neo4j-Repositorys

In Übereinstimmung mit dem Spring Data-Framework unterstützt Neo4j das Abstraktionsverhalten des Spring Data-Repositorys. Das bedeutet, dass der Zugriff auf den zugrunde liegenden persistenten Mechanismus im integrierten Neo4jRepository abstrahiert wird, wo ein Projekt ihn direkt erweitern und die bereitgestellten Operationen sofort verwenden kann.

Die Repositorys können durch kommentierte, benannte oder abgeleitete Finder-Methoden erweitert werden. Die Unterstützung von Spring Data Neo4j-Repositorys basiert ebenfalls auf Neo4jTemplate , sodass die zugrunde liegende Funktionalität identisch ist.

4.1. Erstellen des MovieRepository & PersonRepository

In diesem Lernprogramm werden zwei Repositorys für die Datenpersistenz verwendet:

@Repository public interface MovieRepository extends Neo4jRepository { Movie findByTitle(@Param("title") String title); @Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m") Collection findByTitleContaining(@Param("title") String title); @Query("MATCH (m:Movie)<-[:ACTED_IN]-(a:Person) RETURN m.title as movie, collect(a.name) as cast LIMIT {limit}") List graph(@Param("limit") int limit); } 

Wie Sie können, enthält das Repository einige benutzerdefinierte Operationen sowie die Standardoperationen, die von der Basisklasse geerbt wurden.

Als nächstes haben wir das einfachere PersonRepository , das nur die Standardoperationen hat:

@Repository public interface PersonRepository extends Neo4jRepository  { // }

Möglicherweise haben Sie bereits bemerkt, dass PersonRepository nur die Standardschnittstelle für Spring Data ist. Dies liegt daran, dass es in diesem einfachen Beispiel fast ausreichend ist, die eingebauten Operationen grundsätzlich zu verwenden, da unser Operationssatz mit der Movie- Entität zusammenhängt. Sie können hier jedoch jederzeit benutzerdefinierte Operationen hinzufügen, die einzelne / mehrere integrierte Operationen umschließen können.

4.2. Neo4j- Repositorys konfigurieren

Als nächsten Schritt müssen wir Spring das entsprechende Repository mitteilen , das es in der in Abschnitt 3 erstellten Neo4jConfiguration- Klasse angibt :

@Configuration @ComponentScan("com.baeldung.spring.data.neo4j") @EnableNeo4jRepositories( basePackages = "com.baeldung.spring.data.neo4j.repository") public class MovieDatabaseNeo4jConfiguration { // }

5. Das vollständige Datenmodell

Wir haben bereits begonnen, uns das Datenmodell anzuschauen. Lassen Sie uns nun alles darlegen - den vollständigen Film, die Rolle und die Person . Die Person Entitätsverweise die Filmeinheit durch die Rollenbeziehung.

@NodeEntity public class Movie { @Id @GeneratedValue Long id; private String title; private int released; private String tagline; @Relationship(type="ACTED_IN", direction = Relationship.INCOMING) private List roles; // standard constructor, getters and setters }

Beachten Sie, wie wir Movie mit @NodeEntity kommentiert haben, um anzuzeigen, dass diese Klasse direkt einem Knoten in Neo4j zugeordnet ist.

@JsonIdentityInfo(generator=JSOGGenerator.class) @NodeEntity public class Person { @Id @GeneratedValue Long id; private String name; private int born; @Relationship(type = "ACTED_IN") private List movies; // standard constructor, getters and setters } @JsonIdentityInfo(generator=JSOGGenerator.class) @RelationshipEntity(type = "ACTED_IN") public class Role { @Id @GeneratedValue Long id; private Collection roles; @StartNode private Person person; @EndNode private Movie movie; // standard constructor, getters and setters }

Natürlich sind diese letzten Klassen ähnlich kommentiert und die Referenz -movies - verknüpft Person mit Movie- Klasse über die Beziehung „ACTED_IN“.

6. Datenzugriff mit MovieRepository

6.1. Speichern eines neuen Filmobjekts

Speichern wir einige Daten - zuerst einen neuen Film, dann eine Person und natürlich eine Rolle - einschließlich aller Beziehungsdaten, die wir ebenfalls haben:

Movie italianJob = new Movie(); italianJob.setTitle("The Italian Job"); italianJob.setReleased(1999); movieRepository.save(italianJob); Person mark = new Person(); mark.setName("Mark Wahlberg"); personRepository.save(mark); Role charlie = new Role(); charlie.setMovie(italianJob); charlie.setPerson(mark); Collection roleNames = new HashSet(); roleNames.add("Charlie Croker"); charlie.setRoles(roleNames); List roles = new ArrayList(); roles.add(charlie); italianJob.setRoles(roles); movieRepository.save(italianJob);

6.2. Abrufen eines vorhandenen Filmobjekts nach Titel

Lassen Sie uns nun den eingefügten Film überprüfen, indem Sie ihn mit dem definierten Titel abrufen, der eine benutzerdefinierte Operation ist:

Movie result = movieRepository.findByTitle(title);

6.3. Abrufen eines vorhandenen Filmobjekts durch einen Teil des Titels

Es ist möglich, einen vorhandenen Film anhand eines Teils des Titels zu durchsuchen:

Collection result = movieRepository.findByTitleContaining("Italian");

6.4. Alle Filme abrufen

Alle Filme können einmal abgerufen und auf die richtige Anzahl überprüft werden:

Collection result = (Collection) movieRepository.findAll();

Es gibt jedoch eine Reihe von Suchmethoden mit Standardverhalten, die für Zollanforderungen nützlich sind, und nicht alle werden hier beschrieben.

6.5. Zählen Sie die vorhandenen Filmobjekte

Nach dem Einfügen mehrerer Filmobjekte können wir die Anzahl der Filme beenden:

long movieCount = movieRepository.count();

6.6. Vorhandenen Film löschen

movieRepository.delete(movieRepository.findByTitle("The Italian Job"));

Nach dem Löschen des eingefügten Films können wir nach dem Filmobjekt suchen und überprüfen, ob das Ergebnis null ist:

assertNull(movieRepository.findByTitle("The Italian Job"));

6.7. Alle eingefügten Daten löschen

Es ist möglich, alle Elemente in der Datenbank zu löschen, wodurch die Datenbank leer wird:

movieRepository.deleteAll();

Das Ergebnis dieser Operation entfernt schnell alle Daten aus einer Tabelle.

7. Fazit

In diesem Tutorial haben wir die Grundlagen von Spring Data Neo4j anhand eines sehr einfachen Beispiels durchgearbeitet.

Neo4j ist jedoch in der Lage, sehr fortschrittliche und komplexe Anwendungen mit einer Vielzahl von Beziehungen und Netzwerken zu bedienen. Spring Data Neo4j bietet außerdem erweiterte Funktionen zum Zuordnen kommentierter Entitätsklassen zur Neo4j-Grafikdatenbank.

Die Implementierung der oben genannten Codefragmente und Beispiele finden Sie im GitHub-Projekt - dies ist ein Maven-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.