I have a User
which can have one or more Project
s, where a BELONGS_TO
relationship between the two is maintained in UserEntity
which Project
inherits from.
class User {
@Id @GeneratedValue
var id : Long?
lateinit var name: String
}
class Project : UserEntity() {
lateinit var title: String
}
abstract class UserEntity {
@Id @GeneratedValue
var id : Long?
@Relationship(type="BELONGS_TO", type="OUTGOING")
lateinit var user: User
}
Repositories follow a similar pattern where ProjectRepository
inherits a generic fun findByIdAndUserId()
from UserEntityRepository
:
interface UserRepository: Neo4jRepository<T, Long>
interface ProjectRepository: UserEntityRepository<Project>
@NoRepositoryBean
interface UserEntityRepository<T : UserEntity> : Neo4jRepository<T, Long> {
fun findByIdAndUserId(id: Long, userId: Long): T?
}
And finally a test:
@Test
fun findByIdAndUserId() {
// Set up
val savedUser = userRepo.save(User(name = "John"))
val savedProject = projectRepo.save(Project(title="Neo4j", user=savedUser))
// Find the project
var userProject = projectsRepo.findByIdAndUserId(savedProject.id!!, savedUser.id!!)
// Verify projet was found
assertThat(userProject).isNotNull() // ** FAILS **
}
So, findByIdAndUserId
returns null, it doesn't find the project by project id + user id. In the logs I found this query:
MATCH (n:`Project`)
WHERE n.`id` = {id_0}
MATCH (m0:`User`)
WHERE m0.`id` = {user_id_1}
MATCH (n)-[:`BELONGS_TO`]->(m0)
WITH n
RETURN n,[ [ (n)-[r_b1:`BELONGS_TO`]->(u1:`User`) | [ r_b1, u1 ] ] ], ID(n)
with params {id_0=2, user_id_1=1}
Which at first seems ok because the project has id 2, and the user has id 1 (I checked neo4j), but running this query manually I also get zero results.
I found the problem is how the generated query matches User
's id
, it treats it as a normal property instead of an ID. It works as intended if I swap
WHERE m0.`id` = {user_id_1}
with
WHERE ID(m0) = {user_id_1}
A quick fix would be to add a findByIdAndUserId
method with a custom @Query to every repository interface that inherits UserEntityRepository
, but I'm hoping to avoid this duplication.
Does anyone know of a workaround for this issue? Is it a bug?
At the moment there is no special handling for the id
field in SDN. The problem is somehow related to Spring data neo4j : count relation By EndNode ID and the resulting issue https://jira.spring.io/browse/DATAGRAPH-1049 .
I think if this issue will get resolved SDN will have a better id handling when generating queries.