Search code examples
spring-data-neo4jspring-data-neo4j-4neo4j-ogm

Spring Data Neo4j custom query list params not use converter


NodeEntity:

@NodeEntity(label = "User")
public class UserNode {
    @GraphId
    private Long _gid;

    @Index(unique = true, primary = true)
    @Convert(ObjectIdConverter.class)
    private ObjectId id;
}

Converter:

public class ObjectIdConverter implements AttributeConverter<ObjectId, String>{
    @Override
    public String toGraphProperty(ObjectId value) {
        return ObjectIdUtils.compressed(value);
    }

    @Override
    public ObjectId toEntityAttribute(String value) {
        return ObjectIdUtils.uncompress(value);
    }
}

Repository:

public interface UserNodeRepository extends GraphRepository<UserNode> {
    @Query("MATCH (user:User) WHERE user.id IN {0} RETURN user")
    List<UserNode> findByIdIn(List<ObjectId> ids);
}

UserNodeRepository#findByIdIn is custom query. but the request parameter directly convert to json without using ObjectIdConverter.

Log:

o.n.o.drivers.bolt.request.BoltRequest   : Request: MATCH (user:User) WHERE user.id IN {0} RETURN user with params {0=[{timestamp=1500442853, machineIdentifier=11302907, processIdentifier=11906, counter=4709865, time=1500442853000, date=1500442853000, timeSecond=1500442853}, {timestamp=1500445335, machineIdentifier=11302907, processIdentifier=11906, counter=4709946, time=1500445335000, date=1500445335000, timeSecond=1500445335}, {timestamp=1500447522, machineIdentifier=11302907, processIdentifier=11906, counter=4710014, time=1500447522000, date=1500447522000, timeSecond=1500447522}, {timestamp=1500448399, machineIdentifier=11302907, processIdentifier=11906, counter=4710092, time=1500448399000, date=1500448399000, timeSecond=1500448399}]}

Is this the SDN expectation or what concepts have I lost?


Solution

  • This is not possible for finders with custom @Query. There is no way for OGM to know that your parameter relates to a property with @Convert annotation (the method name is not used at all). To solve this convert to your property type manually instead and use that as a parameter:

    @Query("MATCH (user:User) WHERE user.id IN {0} RETURN user")
    List<UserNode> findByIdIn(List<String> ids);
    

    However this works fine for derived finders - OGM knows the field, and the @Convert annotation with the right converter, from the method name.

    Example with single parameter:

    List<UserNode> findById(ObjectId id);
    

    Unfortunately there seems to be a bug for the IN operator and a collection parameter with:

    // doesn't work
    List<UserNode> findByIdIn(List<ObjectId> ids);
    

    I have created a jira issue.