Quick Start
1. Configuration
Section titled “1. Configuration”@Configuration@ComponentScan("org.drivine")class AppConfig { @Bean fun dataSourceMap(): DataSourceMap { val props = ConnectionProperties( type = DatabaseType.NEO4J, host = "localhost", port = 7687, userName = "neo4j", password = "password", databaseName = "neo4j" ) return DataSourceMap(mapOf("neo" to props)) }}2. Domain Model
Section titled “2. Domain Model”data class Person( val uuid: String, val firstName: String, val lastName: String, val email: String?, val age: Int)3. Repository Pattern
Section titled “3. Repository Pattern”@Componentclass PersonRepository @Autowired constructor( @Qualifier("neoManager") val manager: PersistenceManager) { @Transactional fun findByCity(city: String): List<Person> { return manager.query( QuerySpecification .withStatement("MATCH (p:Person {city: \$city}) RETURN properties(p)") .bind(mapOf("city" to city)) .transform(Person::class.java) ) }
@Transactional fun findById(id: String): Person? { return manager.maybeGetOne( QuerySpecification .withStatement("MATCH (p:Person {uuid: \$id}) RETURN properties(p)") .bind(mapOf("id" to id)) .transform(Person::class.java) ) }
@Transactional fun create(person: Person): Person { return manager.getOne( QuerySpecification .withStatement("CREATE (p:Person) SET p = \$props RETURN properties(p)") .bindObject("props", person) .transform(Person::class.java) ) }
@Transactional fun update(uuid: String, patch: Partial<Person>): Person { val props = patch.toMap() return manager.getOne( QuerySpecification .withStatement( "MATCH (p:Person {uuid: \$uuid}) SET p += \$props RETURN properties(p)" ) .bind(mapOf("uuid" to uuid, "props" to props)) .transform(Person::class.java) ) }}Important: RETURN Clause Best Practices
Section titled “Important: RETURN Clause Best Practices”When using PersistenceManager with Cypher queries, always return a single map or scalar value – not multiple columns. This ensures correct mapping with .transform() and avoids issues with NULL values.
-- WRONG: Multiple columns -- hard to map, NULL values cause errorsRETURN a.name, a.age, b.title
-- CORRECT: Return a single mapRETURN { name: a.name, age: a.age, title: b.title } AS result
-- CORRECT: Return a single property mapRETURN properties(p)
-- CORRECT: Return a scalar valueRETURN count(p) AS totalIf you need to aggregate across multiple nodes, compose the result into a single map in your RETURN clause:
MATCH (p:Proposition)-[:HAS_MENTION]->(m:Mention)WITH m.type AS entityType, m.name AS name, count(p) AS mentionCountORDER BY mentionCount DESCLIMIT 30RETURN { entityType: entityType, name: name, mentionCount: mentionCount} AS resultThis way .transform(MyDto::class.java) can map the result directly to a data class.

