CRUD-Vorgänge können nicht über Neo4j in Spring Boot implementiert werden

Lesezeit: 9 Minuten

Benutzer-Avatar
Toni Marke

Ich habe ein Problem mit der Umsetzung CRUD Operationen durch die Neo4j Abfrage in Spring Boot.

Mein Problem liegt bei beiden CityRepositorium, RouteRepository, ShortestPathRepository und Route Einheit.

1) Als ich anrief Liste alle auf und getById Methode von CityRepositoriumIch bekomme leere Stadt Name mit Auflistung seiner Route, nachdem die unten gezeigte Route hinzugefügt wurde.

[
    {
        "id": "077d1b16-9a4b-4fb0-947b-52031774d949",
        "name": "London",
        "routes": []
    },
    {
        "id": "077d1b16-9a4b-4fb0-947b-52031774d949",
        "name": null,
        "routes": [
            {
                "id": "6db5dd3f-085a-4d50-b025-4f0bee847fcf",
                "from": "London",
                "destination": "Berlin",
                "departureTime": "9:00",
                "arriveTime": "11:30",
                "duration": 2.5
            }
        ]
    }
]

2 ) (bearbeitet) Nachdem Sie eine beliebige Route von City hinzugefügt und angerufen haben Liste alle auf of City habe ich dieses im Screenshot gezeigte Ergebnis erhalten.

Geben Sie hier die Bildbeschreibung ein
Geben Sie hier die Bildbeschreibung ein

Hier mein Projektlink: Projekt

Hier ist die Postboten-Anfrage-Sammlung: Verknüpfung

Hier sind Screenshots zu meinen Problemen: Verknüpfung

Wie kann ich mein Problem beheben?

Hier sind meine Einheiten als Stadt und Route, die unten gezeigt werden.

Stadt

public class City {

    @Id
    @Property
    private UUID id;

    @Property
    private String name;

    @Relationship(type = "ROUTES", direction = Relationship.Direction.OUTGOING)
    private Set<Route> routes = new HashSet<>();

    public City(String name) {
        this.name = name;
    }
}

Route

public class Route {

    @Id
    @Property
    private UUID id;

    @Property
    private String from;

    @Property
    private String destination;

    @Property
    private String departureTime;

    @Property
    private String arriveTime;

    @Property
    private Double duration;
}

Hier ist mein CityRepositorium unten gezeigt.

public interface CityRepository extends Neo4jRepository<City,UUID> {

    @Query("MATCH (city:City) OPTIONAL MATCH (city)-[r:ROUTES]->(route:Route) RETURN city, collect(r), collect(route)")
    List<City> listAll();

    @Query("MATCH (city:City {id: $cityId}) OPTIONAL MATCH (city)-[r:ROUTES]->(route:Route) RETURN city, collect(r), collect(route)")
    City getById(UUID cityId);

    @Query("MATCH (city:City {name: $cityName}) RETURN city")
    City getByCityName(String cityName);

    @Query("CREATE (city:City {id: randomUUID(), name: $cityName}) RETURN city")
    City saveCity(String cityName);

    @Query("MATCH (city:City {id: $cityId}) SET city.name = $cityName RETURN city")
    City updateCity(UUID cityId, String cityName);

    @Query("MATCH (city:City {id: $cityId}) DELETE city")
    void deleteCity(UUID cityId);
}

Hier ist mein RouteRepository unten gezeigt.

public interface RouteRepository extends Neo4jRepository<Route,UUID> {

    @Query("MATCH (city:City {id: $cityId})-[:ROUTES]->(route:Route) RETURN route")
    List<Route> listAllByCityId(UUID cityId);

    @Query("MATCH (route:Route {id: $routeId}) RETURN route")
    Route getById(UUID routeId);

    @Query("CREATE (city:City {id: $cityId})-[:ROUTES]->(route:Route {id: randomUUID(), from: $from, destination: $destination, departureTime: $departureTime," +
            "arriveTime: $arriveTime, duration: $duration}) " +
            "RETURN route")
    Route saveRoute(UUID cityId, String from, String destination, String departureTime,
                    String arriveTime, double duration);

    @Query("MATCH (city:City {id: $cityId})-[:ROUTES]->(route:Route {id: $routeId}) " +
            "SET route.from = $from, route.destination = $destination,route.departureTime = $departureTime," +
            "route.arriveTime = $arriveTime, route.duration = $duration RETURN route")
    Route updateRoute(UUID cityId, UUID routeId, String from, String destination,String departureTime,
                      String arriveTime,double duration);

    @Query("MATCH (city:City {id: $cityId})-[r:ROUTES]->(route:Route {id: $routeId}) DELETE r, route")
    void deleteRoute(UUID cityId, UUID routeId);
}

  • “Ich habe ein Problem in …” — Was ist das Problem? Das Speichern aktualisiert nicht tatsächlich die neuen Werte? Oder liegt ein Fehler vor? Wenn ja, was ist der Fehler?

    – Knox

    22. Mai um 19:52 Uhr

  • @Knox Ich habe alle Informationen zu meinen Problemen erklärt und meinen Beitrag bearbeitet.

    – Toni Marke

    25. Mai um 8:47 Uhr

  • @ Knox Ich habe es bereits erklärt.

    – Toni Marke

    5. Juni um 22:13 Uhr

  • @Knox Ich brauche wirklich deine Hilfe.

    – Toni Marke

    6. Juni um 20:06 Uhr

Benutzer-Avatar
Meistermeier

Drittes Update: Es gibt ein Problem mit der benutzerdefinierten Speicherabfrage. Mit dem CREATE.... an Ort und Stelle wird Neo4j immer neue Entitäten erstellen. Der sicherste Weg, eine neue Beziehung mit mindestens einem vorhandenen Knoten zu erstellen, besteht darin, den vorhandenen Knoten abzugleichen und ihn dann zu verwenden, indem Sie die Referenz in der benennen MERGE Aussage. Ich habe mein Projekt aktualisiert, aber hier ist im Grunde die Lösung:

@Query("MATCH (city:City {id: $cityId}) " +
       "MERGE (city)-[:ROUTES]->(route:Route {id: randomUUID(), from: $from, destination: $destination, departureTime: $departureTime," +
            "arriveTime: $arriveTime, duration: $duration}) " +
            "RETURN route")
Route saveRoute(UUID cityId, String from, String destination, String departureTime,
                    String arriveTime, double duration);

Zweites Update: In Ordnung, ich habe das Projekt aktualisiert, um Webtests einzuschließen, die jetzt auf der Controller-Ebene beginnen. Bitte schauen Sie es sich an und passen Sie es an, um die Fehler zu reproduzieren, die ich gerade übersehe.

1 und 4 kann ich nicht reproduzieren, bitte schau mal com.springshortpath.app.ApplicationWebTests#listCitiesWithRoutes / com.springshortpath.app.ApplicationWebTests#listRoutesByCity.

Für 2 und 3: Das Abfragemuster verlangt, dass (mindestens) eine Route definiert ist. Wenn Sie auch Städte ohne Routen erhalten möchten, müssen Sie sich für optionales Match entscheiden.

Für 5: Die Repositorys von Spring Data Neo4j können Entitätsdefinitionen nur als Rückgabetyp verarbeiten. Wenn Sie den Typ des Java-Treibers verwenden möchten, verwenden Sie bitte SDNs Neo4jClient für Interaktion. SDN-Dokumentation / Neo4jClient

Update zur bearbeiteten Frage:

Zum Löschen der Route: Der Fehler besagt, dass die Beziehung vorher entfernt werden muss. Die richtige Abfrage sollte sein MATCH (city:City {id: $cityId})-[r:ROUTES]->(route:Route {id: $routeId}) DELETE r, route

Für diejenigen, die keine Routen nach Stadt-UUID finden können: Die Richtung der Beziehung ist falsch, die richtige ist: MATCH (city:City {id: $cityId})-[:ROUTES]->(route:Route) RETURN route

Ich konnte die anderen Probleme nicht reproduzieren, habe aber Testfälle für das erstellt, was ich in einem Fork Ihres Repositorys verstehe: https://github.com/meistermeier/SpringBootNeo4jShortestPath

Alte Antworten: Im Allgemeinen sehe ich ein Missverständnis von id Eigentum vs id eines Knotens.

1) Als ich die saveCity-Methode aufrief, wurde der Wert mit seinem ID-Wert 0 hinzugefügt. Ich habe keine Ahnung, warum id 0 zugewiesen ist.

Sie haben Ihre ID als interne Neo4j-ID definiert.

@Id
@GeneratedValue
private Long id;

Als Ergebnis weist SDN diesen Wert beim Speichern dem ID-Feld zu. Die interne ID eines Knotens wird über verglichen/abgerufen id(node) in der Cypher-Abfrage.

3) Als ich die getCityById-Methode aufrief, konnte ich kein Ergebnis sehen

Als Konsequenz die Abfrage MATCH (city:City {id: $cityId}) RETURN city sucht nicht nach dem richtigen ID-Feld, sondern nach einer Eigenschaft id.

2) Als ich die listAll-Methode aufrief, wurden alle Werte aufgelistet (es gibt keinen Routenwert, da ich keine Route hinzufügen kann).

Wenn Sie sich immer noch auf die beziehen CityRepository hier sieht man nichts Route weil du sie nicht zurücksendest. Ändern der Abfrage in MATCH (city:City)-[r:ROUTES]->(route:Route) RETURN city, collect(r), collect(route) (oder das Hinzufügen einer optionalen Klausel, um die Routen zu erhalten, anstatt das Muster zu erfordern), fügt auch die hinzu Routes zum entsprechenden Cities.

4) Als ich die updateCity-Methode aufrief, konnte ich kein Ergebnis sehen.

Dies sollte wie erwartet funktionieren, aber ich gehe davon aus, dass Sie sich auf etwas anderes beziehen, indem Sie sagen konnte kein Ergebnis sehen. Es sollte das gleiche Ergebnis wie die Methode sein City getByCityName(String cityName) einschließlich der Änderung der ID-Eigenschaft.

Für den Rest der Fragen wette ich, dass es das ist node.id Eigentum vs. id(node) Problem wieder. Also im Grunde jeder Ort, den Sie haben (n:City|Route...{id: $id}) soll werden (n:City|Route...) WHERE id(n) = $id.

  • Ich bin jetzt etwas ratlos. Könnten Sie Ihrem Projekt bitte Testfälle hinzufügen, um mir genau zu zeigen, was Sie erwarten und was nicht funktioniert? Ich denke, das ist der beste Weg, Ihnen so schnell wie möglich zu helfen, ohne falsche Annahmen zu haben.

    – Meistermeier

    6. Juni um 22:30 Uhr

  • Meine Antwort aktualisiert

    – Meistermeier

    7. Juni um 1:57

  • Ich möchte Ihnen für Ihre Antwort danken. Ich hoffe, Sie können auch listAll und getCitybyId in CityRepository lösen, nachdem Sie sich mit der Berechnung des kürzesten Weges befasst haben. Ich denke, Sie können auch mein Repository zum Testen forken.

    – Toni Marke

    7. Juni um 6:24

  • Ich habe auch die Abholung von Postboten in der Post hinzugefügt.

    – Toni Marke

    7. Juni um 6:37

  • Ich habe meinen Beitrag gerade nochmal aktualisiert.

    – Toni Marke

    7. Juni um 6:55

Sieht so aus, als ob allen Java-Objekten Getter-Setter-Methoden fehlen. Bitte helfen Sie bei der manuellen Generierung, dann werden Ihre Projektfehler verschwinden.

  • Ihre Antwort könnte durch zusätzliche unterstützende Informationen verbessert werden. Bitte bearbeiten Sie, um weitere Details wie Zitate oder Dokumentation hinzuzufügen, damit andere bestätigen können, dass Ihre Antwort richtig ist. Weitere Informationen zum Verfassen guter Antworten finden Sie in der Hilfe.

    – Gemeinschaft
    bot

    28. Mai um 16:54 Uhr

  • Er verwendet Lombok, hat aber die Klassendekorateure nicht einbezogen.

    – H3AR7B3A7

    6. Juni um 20:40 Uhr

  • @ H3AR7B3A7 Ich habe gerade meinen Beitrag erneut aktualisiert, aber dies sind immer noch einige Fehler, die ich nicht lösen konnte. Ist es möglich, es durchzusehen, wenn es Ihnen nichts ausmacht?

    – Toni Marke

    7. Juni um 11:05 Uhr

Nachfolgend finden Sie eine Antwort von meiner Seite.

1) Als ich die saveCity-Methode aufrief, wurde der Wert mit seinem ID-Wert 0 hinzugefügt. Ich habe keine Ahnung, warum id 0 zugewiesen ist.

Meine Antwort: Wenn Sie versuchen, den db-ID-Wert hinzuzufügen, beginnt er bei Null, was standardmäßig Null ist. Wenn Sie den zweiten Datensatz hinzufügen, ist der ID-Wert 1 … ähnlich, wenn Sie den dritten Datensatz hinzufügen, ist der ID-Wert 2 und so weiter.

2) Als ich die listAll-Methode aufrief, wurden alle Werte aufgelistet (es gibt keinen Routenwert, da ich keine Route hinzufügen kann).

Meine Antwort: Dies ist das Standardverhalten.

  1. Als ich die getCityById-Methode aufgerufen habe, konnte ich kein Ergebnis sehen. Meine Antwort: Sie können mit getById oder getId

4)4) Als ich die updateCity-Methode aufrief, konnte ich kein Ergebnis sehen.

5) Als ich die Methode deleteCity aufrief, sah ich „Stadt ist gelöscht“, aber als ich die Methode listAll aufrief, sah ich diesen Wert. Wie ich es verstanden habe, kann die Löschmethode nicht bearbeitet werden.

6) Als ich saveRoute anrief, wurde es hinzugefügt, aber es gibt ein ID-Problem. Ich kann seinen Wert nicht sehen, wenn ich die Methode listAll of City aufgerufen habe.

7) Als ich die Methode getRouteById aufrief, konnte ich kein Ergebnis sehen

8) Als ich die Methode listAll aufrief, konnte ich kein Ergebnis sehen.

9) Als ich die updateRoute-Methode aufrief, konnte ich kein Ergebnis sehen.

10) Als ich die Methode deleteRoute aufrief, sah ich „Route wurde gelöscht“, aber als ich die Methode listAll aufrief, konnte ich kein Ergebnis sehen. Keine Ahnung ob es gelöscht wird.

Meine Antwort: Für 4, 5, 6, 7, 8, 9 denke ich, dass Sie sich nicht verpflichten oder in Bezug auf die Programmierung sparen. nach der Commit-Operation werden nur die Ergebnisse gespeichert oder aktualisiert.

  • Sie konnten mir keine Lösungsmöglichkeit nennen.

    – Toni Marke

    5. Juni um 13:51 Uhr

1019080cookie-checkCRUD-Vorgänge können nicht über Neo4j in Spring Boot implementiert werden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy