shelll
shelll

Reputation: 3373

Neo4jRepository saves empty node from Kotlin data class

I have a Kotlin data class node for Neo4j nodes:

@NodeEntity
data class MyNode (
    @Id @GeneratedValue var dbId: Long? = null,
    @Index(unique = true) val name: String,
    val description: String
)

and a Spring repository:

interface MyNodesRepository : Neo4jRepository<MyNode, Long>

Then, when I save a node into the DB via this repository it is empty, without any properties:

val node = MyNode(null, "name 1", "lorem ipsum")
myNodesRepository.save(node)

after the save(node) call, the node.dbId is set to the Neo4j's internal id i.e. it is null before save() and has a value afterwards. I can also see the node in the Neo4j browser, but it does not have name and description properties.

After that, when I try to load all nodes the call crashes with InvalidDataAccessApiUsageException because it cannot deserialize/map the nodes with null/missing name and description:

val allNodes = myNodesRepository.findAll()

If I add a custom save method to my repository, where I manually create the node with CQL query, then everything works.

interface MyNodesRepository : Neo4jRepository<MyNode, Long> {
    @Query(
        "MERGE (mn:MyNode {name:{name}})\n" +
            "ON CREATE SET m += {description:{description}}"
    )
    fun customSave(@Param("name") name: String, @Param("description") description: String)
}

Now the findAll() loads my newly created and/or updated nodes.

I am using org.springframework.boot:spring-boot-starter-data-neo4j:2.1.6.RELEASE and this is inside a Spring Boot CLI application so no web server and RestControllers.

What am I doing wrong?

EDIT: This is now solved in Neo4j OGM 3.1.13

Upvotes: 0

Views: 140

Answers (1)

shelll
shelll

Reputation: 3373

EDIT: This is now solved in Neo4j OGM 3.1.13 and the workaround below is not needed anymore.

ORIGINAL ANSWER

After few days of debugging it looks like there is a bug in Neo4j OGM for Kotlin data classes where it does not save val properties -- both in data classes and normal classes. So change from val properties:

@NodeEntity
data class MyNode (
    @Id @GeneratedValue var dbId: Long? = null,
    @Index(unique = true) val name: String,
    val description: String
)

to all var properties:

@NodeEntity
data class MyNode (
    @Id @GeneratedValue var dbId: Long? = null,
    @Index(unique = true) var name: String,
    var description: String
)

works. Now both saving and loading works, but it is not idiomatic Kotlin.

So at least we have a workaround.

Upvotes: 0

Related Questions