Mapping Results to Java Objects

Introduction

The driver includes an object mapping feature that allows you to map query results directly to Java objects. This feature simplifies the process of working with Neo4j data in Java applications by eliminating the need for manual mapping with raw data types.

This feature was introduced in the driver version 5.28.5.

Object Graph Mapping (OGM)

The driver’s new object mapping is not a full-fledged OGM solution. For a more comprehensive option, check out the Neo4j OGM library.

Domain Model

Nodes are represented by domain classes.

For the Person domain class, create a new file in src/main/java/com/neo4j/app and name it Person.java.

This example will use Java records (rather than class), but classes work similarly.
Java
public record Person(String id,
                     String name) {
}

Querying and Mapping Results

Open the src/main/java/com/neo4j/app/App.java file and add a method to query for a person by name and return an entity mapped to your Person record.

Querying and Mapping Results

Java
final String personCypher = """
    MATCH (person:Person {name: $name})
    RETURN person
    """;
final String name = "Tom Hanks";

var person = driver.executableQuery(personCypher)
    .withParameters(Map.of("name", name))
    .execute()
    .records()
    .stream()
    .map(record -> record.get("person").as(Person.class)) // (1)
    .findFirst()
    .orElseThrow(() -> new RuntimeException("Person not found")); // (2)

System.out.println(person); // (3)
  1. .as(Person.class) returns a single record mapped to the Person class

  2. .findFirst().orElseThrow() returns the first record or throws an exception if not found

  3. Print the person object to the console

Adding a Connecting Node

You can return a graph by adding the Movie node to the domain and connecting it to the Person node.

Java
public record Movie(String id,
                    String title,
                    List<Person> actors) {
}

Querying and Returning a Graph

Queries must return the results that match the domain model’s structure.

This query returns a single Movie node with a list of Person nodes as actors. The query uses the COLLECT clause to gather the actors into a list.

Java
final String movieCypher = """
    MATCH (movie:Movie)
    LIMIT 1
    RETURN movie {
        .*,
        actors: COLLECT {
            MATCH (actor:Person)-[r:ACTED_IN]->(movie)
            RETURN actor
        }
    }
    """;

Mapping Results

Results are mapped to the Movie class using the .as(Movie.class) method - automatically mapping the actors list to a list of Person objects.

Missing properties

Only the movieId and title are defined in the domain class so only those are mapped from the node in Neo4j. If you want to include more properties, you can add them to the class definition.

Java
var movie = driver.executableQuery(movieCypher)
            .execute()
            .records()
            .stream()
            .map(record -> record.get("movie").as(Movie.class))
            .findFirst()
            .orElseThrow(() -> new RuntimeException("No movie found"));

System.out.println(movie);

Summary

In this lesson, you learned how to use the Neo4j Java driver’s object mapping feature to map query results directly to Java objects.