I'm trying to do the following:
Create Person and Dog nodes which have the following relationships:
Person has 2 relationships: TEAMMATE with a list of Persons and 'OWNER_OF' with a list of dogs
Dog has 1 relationship: OWNED_BY with a single person
So for example: I have 2 people: Chris and Roger. Roger is a teammate of Chris and 1 dog: Ghost which is owned by Chris
My endgame is to query the following: get me all the teammates of a person who is the owner of a dog named Ghost (the result is Roger from the example)
I created the following code:
@Node
data class Dog(
@Id @GeneratedValue
val id: Long?,
val name: String,
@Relationship(type = "OWNED_BY")
var owner: Person? = null) {
constructor(name: String) : this(null, name)
override fun toString(): String {
return "$name's owner => ${owner?.name}"
}
override fun hashCode(): Int {
return id?.hashCode() ?: super.hashCode()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Dog
if (id != other.id) return false
return name == other.name
}
}
@Node
data class Person(
@Id @GeneratedValue
val id: Long?,
val name: String,
@Relationship(type = "TEAMMATE")
var teammates: MutableSet<Person> = mutableSetOf(),
@Relationship(type = "OWNER_OF")
var dogs: MutableSet<Dog> = mutableSetOf()) {
constructor(name: String) : this(null, name)
fun addTeammates(person: Set<Person>) {
teammates.addAll(person)
}
fun addDog(dogs: Set<Dog>) {
this.dogs.addAll(dogs)
}
override fun toString(): String {
val teammatesList = teammates.stream().map(Person::name).toList()
val dogsList = dogs.stream().map(Dog::name).toList()
return "$name's teammates => $teammatesList, dogs => $dogsList"
}
override fun hashCode(): Int {
return id?.hashCode() ?: super.hashCode()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Person
if (id != other.id) return false
return name == other.name
}
}
@Repository
interface DogRepository : Neo4jRepository<Dog, Long>
@Repository
interface PersonRepository : Neo4jRepository<Person, Long>
I'm creating the following demo:
@PostMapping("/demo2")
fun addDemo2() {
// Delete existing data (optional)
personRepository.deleteAll()
dogRepository.deleteAll()
val chris = Person("Chris")
val roger = Person("Roger")
val ghost = Dog("Ghost")
// Establish the relationships manually
ghost.owner = chris
chris.dogs.add(ghost)
chris.addTeammates(setOf(roger))
// Save the entities
personRepository.save(chris)
dogRepository.save(ghost)
}
}
when I run this, I'm getting the following error:
java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.orElseThrow(Optional.java:377) ~[na:na]
at org.springframework.data.neo4j.core.TemplateSupport.retrieveOrSetRelatedId(TemplateSupport.java:412) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
at org.springframework.data.neo4j.core.Neo4jTemplate.lambda$processNestedRelations$28(Neo4jTemplate.java:839) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
at org.springframework.data.neo4j.core.mapping.AssociationHandlerSupport.lambda$doWithAssociations$0(AssociationHandlerSupport.java:51) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:317) ~[spring-data-commons-3.1.5.jar:3.1.5]
at org.springframework.data.neo4j.core.mapping.AssociationHandlerSupport.doWithAssociations(AssociationHandlerSupport.java:49) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
at org.springframework.data.neo4j.core.Neo4jTemplate.processNestedRelations(Neo4jTemplate.java:731) ~[spring-data-neo4j-7.1.5.jar:7.1.5]
....
Any idea?