spring-data-neo4j
Install this skill
npx skills add giuseppe-trisciuoglio/developer-kitWorks across Claude Code, Cursor, Codex, Copilot & Antigravity
Spring Data Neo4j (SDN) bridges the gap between object-oriented domain models and graph data structures. It maps Java objects to Neo4j nodes and relationships, handling complex graph traversals through familiar Spring Repository patterns. The framework supports both blocking imperative styles and non-blocking reactive paradigms using Project Reactor. Developers can define entity relationships via annotations, implement automated query derivation from interface methods, or execute raw Cypher queries when specific graph traversals are required. By integrating directly with Spring Boot's dependency injection and transaction management, SDN simplifies graph database interaction. It manages entity state, ID generation strategies, and mapping conversions, allowing teams to focus on business logic rather than manual database connectivity or low-level driver serialization concerns.
When to Use This Skill
- •Building social networking applications with deep multi-level relationship traversals
- •Modeling complex domain data where connections between entities carry significant weight
- •Implementing recommendation engines based on path discovery and node similarities
- •Managing hierarchical or network-based data structures in a microservices environment
How to Invoke This Skill
Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:
- “setup spring data neo4j in my boot project
- “map a graph relationship between two entities in java
- “write a custom cypher query inside a spring repository
- “how to use reactive neo4j repository with spring boot
- “define a node entity with a business key in neo4j
- “troubleshoot relationship mapping in spring data neo4j
Pro Tips
- 💡Always define clear relationship directions and types to optimize query performance and ensure semantic clarity in your graph model.
- 💡Utilize the `Neo4jTemplate` for complex, dynamic queries or batch operations that are difficult to express via derived repository methods.
- 💡Leverage Spring's `@Transactional` annotation for graph operations to ensure data consistency, especially when modifying multiple nodes or relationships.
What this skill does
- •Object-Graph mapping for Java entities using @Node and @Relationship
- •Automatic repository implementation for standard CRUD and derived query methods
- •Support for reactive data access using Flux and Mono via ReactiveNeo4jRepository
- •Custom Cypher execution with parameter binding via @Query annotations
- •Configurable ID generation strategies for business keys versus synthetic primary keys
When not to use it
- ✕Handling simple key-value pairs or highly structured, tabular data better suited for RDBMS
- ✕Applications with extremely high write-heavy throughput requirements where graph locks create bottlenecks
- ✕Small projects where the overhead of an graph database and OGM framework introduces unnecessary complexity
Example workflow
- Add the spring-boot-starter-data-neo4j dependency to the project build file
- Define POJO domain classes annotated with @Node to represent graph entities
- Establish relationships between entities using @Relationship annotations
- Create repository interfaces extending Neo4jRepository for data access
- Inject repositories into service beans to perform graph queries and persistence
Prerequisites
- –Active Neo4j database instance (version 4.x or 5.x)
- –Familiarity with Cypher query language basics
- –Spring Boot project foundation
Pitfalls & limitations
- !Mixing imperative and reactive repository styles in the same application leads to unpredictable threading and connectivity issues
- !Over-fetching large subgraphs into memory by defining overly eager relationships
- !Incorrect handling of bidirectional relationships resulting in infinite recursion during mapping
FAQ
How it compares
SDN automates the complex mapping of graph traversals to objects, which is significantly more error-prone when manually managing raw database drivers and Cypher result parsing.
📄 Full skill instructions — original source: giuseppe-trisciuoglio/developer-kit
## When to Use This Skill
To use this skill when you need to:
- Set up Spring Data Neo4j in a Spring Boot application
- Create and map graph node entities and relationships
- Implement Neo4j repositories with custom queries
- Write Cypher queries using @Query annotations
- Configure Neo4j connections and dialects
- Test Neo4j repositories with embedded databases
- Work with both imperative and reactive Neo4j operations
- Map complex graph relationships with bidirectional or unidirectional directions
- Use Neo4j's internal ID generation or custom business keys
## Overview
Spring Data Neo4j provides three levels of abstraction for Neo4j integration:
- **Neo4j Client**: Low-level abstraction for direct database access
- **Neo4j Template**: Medium-level template-based operations
- **Neo4j Repositories**: High-level repository pattern with query derivation
Key features include reactive and imperative operation modes, immutable entity mapping, custom query support via @Query annotation, Spring's Conversion Service integration, and full support for graph relationships and traversals.
## Quick Setup
### Dependencies
**Maven:**
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>**Gradle:**
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
}### Configuration
**application.properties:**
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret**Configure Neo4j Cypher-DSL Dialect:**
@Configuration
public class Neo4jConfig {
@Bean
Configuration cypherDslConfiguration() {
return Configuration.newConfig()
.withDialect(Dialect.NEO4J_5).build();
}
}## Basic Entity Mapping
### Node Entity with Business Key
@Node("Movie")
public class MovieEntity {
@Id
private final String title; // Business key as ID
@Property("tagline")
private final String description;
private final Integer year;
@Relationship(type = "ACTED_IN", direction = Direction.INCOMING)
private List<Roles> actorsAndRoles = new ArrayList<>();
@Relationship(type = "DIRECTED", direction = Direction.INCOMING)
private List<PersonEntity> directors = new ArrayList<>();
public MovieEntity(String title, String description, Integer year) {
this.title = title;
this.description = description;
this.year = year;
}
}### Node Entity with Generated ID
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue
private Long id;
private final String title;
@Property("tagline")
private final String description;
public MovieEntity(String title, String description) {
this.id = null; // Never set manually
this.title = title;
this.description = description;
}
// Wither method for immutability with generated IDs
public MovieEntity withId(Long id) {
if (this.id != null && this.id.equals(id)) {
return this;
} else {
MovieEntity newObject = new MovieEntity(this.title, this.description);
newObject.id = id;
return newObject;
}
}
}## Repository Patterns
### Basic Repository Interface
@Repository
public interface MovieRepository extends Neo4jRepository<MovieEntity, String> {
// Query derivation from method name
MovieEntity findOneByTitle(String title);
List<MovieEntity> findAllByYear(Integer year);
List<MovieEntity> findByYearBetween(Integer startYear, Integer endYear);
}### Reactive Repository
@Repository
public interface MovieRepository extends ReactiveNeo4jRepository<MovieEntity, String> {
Mono<MovieEntity> findOneByTitle(String title);
Flux<MovieEntity> findAllByYear(Integer year);
}**Imperative vs Reactive:**
- Use
Neo4jRepository for blocking, imperative operations- Use
ReactiveNeo4jRepository for non-blocking, reactive operations- **Do not mix imperative and reactive in the same application**
- Reactive requires Neo4j 4+ on the database side
## Custom Queries with @Query
@Repository
public interface AuthorRepository extends Neo4jRepository<Author, Long> {
@Query("MATCH (b:Book)-[:WRITTEN_BY]->(a:Author) " +
"WHERE a.name = $name AND b.year > $year " +
"RETURN b")
List<Book> findBooksAfterYear(@Param("name") String name,
@Param("year") Integer year);
@Query("MATCH (b:Book)-[:WRITTEN_BY]->(a:Author) " +
"WHERE a.name = $name " +
"RETURN b ORDER BY b.year DESC")
List<Book> findBooksByAuthorOrderByYearDesc(@Param("name") String name);
}**Custom Query Best Practices:**
- Use
$parameterName for parameter placeholders- Use
@Param annotation when parameter name differs from method parameter- MATCH specifies node patterns and relationships
- WHERE filters results
- RETURN defines what to return
## Testing Strategies
### Neo4j Harness for Integration Testing
**Test Configuration:**
@DataNeo4jTest
class BookRepositoryIntegrationTest {
private static Neo4j embeddedServer;
@BeforeAll
static void initializeNeo4j() {
embeddedServer = Neo4jBuilders.newInProcessBuilder()
.withDisabledServer() // No HTTP access needed
.withFixture(
"CREATE (b:Book {isbn: '978-0547928210', " +
"name: 'The Fellowship of the Ring', year: 1954})" +
"-[:WRITTEN_BY]->(a:Author {id: 1, name: 'J. R. R. Tolkien'}) " +
"CREATE (b2:Book {isbn: '978-0547928203', " +
"name: 'The Two Towers', year: 1956})" +
"-[:WRITTEN_BY]->(a)"
)
.build();
}
@AfterAll
static void stopNeo4j() {
embeddedServer.close();
}
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", embeddedServer::boltURI);
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
registry.add("spring.neo4j.authentication.password", () -> "null");
}
@Autowired
private BookRepository bookRepository;
@Test
void givenBookExists_whenFindOneByTitle_thenBookIsReturned() {
Book book = bookRepository.findOneByTitle("The Fellowship of the Ring");
assertThat(book.getIsbn()).isEqualTo("978-0547928210");
}
}## Examples
Progress from basic to advanced examples covering complete movie database, social network patterns, e-commerce product catalogs, custom queries, and reactive operations.
See [examples](./references/examples.md) for comprehensive code examples.
## Best Practices
### Entity Design
- Use immutable entities with final fields
- Choose between business keys (@Id) or generated IDs (@Id @GeneratedValue)
- Keep entities focused on graph structure, not business logic
- Use proper relationship directions (INCOMING, OUTGOING, UNDIRECTED)
### Repository Design
- Extend
Neo4jRepository for imperative or ReactiveNeo4jRepository for reactive- Use query derivation for simple queries
- Write custom @Query for complex graph patterns
- Don't mix imperative and reactive in same application
### Configuration
- Always configure Cypher-DSL dialect explicitly
- Use environment-specific properties for credentials
- Never hardcode credentials in source code
- Configure connection pooling based on load
### Testing
- Use Neo4j Harness for integration tests
- Provide test data via
withFixture() Cypher queries- Use
@DataNeo4jTest for test slicing- Test both successful and edge-case scenarios
### Architecture
- Use constructor injection exclusively
- Separate domain entities from DTOs
- Follow feature-based package structure
- Keep domain layer framework-agnostic
### Security
- Use Spring Boot property overrides for credentials
- Configure proper authentication and authorization
- Validate input parameters in service layer
- Use parameterized queries to prevent Cypher injection
## References
For detailed documentation including complete API reference, Cypher query patterns, and configuration options:
- [Annotations Reference](./references/reference.md#annotations-reference)
- [Cypher Query Language](./references/reference.md#cypher-query-language)
- [Configuration Properties](./references/reference.md#configuration-properties)
- [Repository Methods](./references/reference.md#repository-methods)
- [Projections and DTOs](./references/reference.md#projections-and-dtos)
- [Transaction Management](./references/reference.md#transaction-management)
- [Performance Tuning](./references/reference.md#performance-tuning)
### External Resources
- [Spring Data Neo4j Official Documentation](https://docs.spring.io/spring-data/neo4j/reference/)
- [Neo4j Developer Guide](https://neo4j.com/developer/)
- [Spring Data Commons Documentation](https://docs.spring.io/spring-data/commons/reference/)
How to Use This Skill Unit
Option A: Project-Specific (Recommended)
- Click "Download" above
- In your project, create the directory:
.agent/skills/spring-data-neo4j/ - Save the file as
SKILL.md - The agent will automatically discover the skill based on its description.
Option B: Global Installation (All Agents)
Save the file to these locations to make it available across all projects:
- Claude Code:
~/.claude/skills/giuseppe-trisciuoglio/developer-kit/spring-data-neo4j/SKILL.md - Cursor:
~/.cursor/skills/giuseppe-trisciuoglio/developer-kit/spring-data-neo4j/SKILL.md - Antigravity:
~/.gemini/antigravity/skills/giuseppe-trisciuoglio/developer-kit/spring-data-neo4j/SKILL.md
🚀 Install with CLI:npx skills add giuseppe-trisciuoglio/developer-kit