Пользовательские запросы не работают с проекциями интерфейса в репозиториях Spring Data Neo4j

#java #spring #spring-boot #spring-data #spring-data-neo4j

#java #spring #spring-boot #spring-данные #spring-data-neo4j

Вопрос:

Чтобы исключить некоторые поля объекта, я создал проекцию интерфейса, которая возвращает только некоторые из полей.

Я хотел добавить метод в интерфейс репозитория (который расширяет Neo4jRepository), который использует пользовательский запрос, написанный в Cypher (с использованием аннотации @Query)

Этот метод работает, если я устанавливаю возвращаемому объекту значение Entity, но он возвращается null , когда возвращаемому объекту присваивается значение projection. Прогнозы работают с обычными методами репозитория (без пользовательских запросов)

Пример кода: Также — я использую lombok, но сомневаюсь, что здесь это имеет какое-либо значение

PersonEntity.java

 @NodeEntity
@Data
public class Person {
  @Id
  @GeneratedValue
  private Long id;
  @Property("first_name")
  private String firstName;
  @Property("last_name")
  private String lastName;
  @Property("is_man")
  private boolean isMan;
  

PersonProjection.java

 public interface PersonProjection {
  Long getId();
  String getFirstName();
  boolean getIsMan();
}
  

PersonRepository.java

 public interface PersonRepository extends Neo4jRepository<Person, Long> {
  @Query("MATCH (n:`Person`) WHERE n.`is_man` = true WITH n RETURN n")
  List<PersonProjection> findMen(); // doesn't work, returns null

  List<PersonProjection> findAllByIsManTrue(); // works, returns the list of men
}
  

Некоторые вещи, на которые следует обратить внимание:

  1. Этот шифровальный запрос корректен на 100%. Протестировал его в Neo4j Desktop, и он работает так, как ожидалось
  2. Конечно, этот пример тривиален, и обычно мне не нужен пользовательский запрос для этого, но проблема вернется ко мне, когда возникнут более сложные запросы
  3. Как я уже сказал, метод пользовательского запроса работает, когда я использую entity вместо projection. И при использовании проекции в журнале отладки говорится, looking for concrete class to resolve label: Person так что, возможно, это каким-то образом заставляет использовать entity? Просто вещь, о которой я думал
  4. Я использую последнюю версию spring-boot-starter-data-neo4j

Есть ли способ это исправить? Как я мог это сделать? И если исправление невозможно, каким другим способом я мог бы подойти к этой проблеме?

Комментарии:

1. Вы пытались аннотировать PersonProjection с помощью @QueryResult (org.springframework.data.neo4j.annotation. Результат запроса)

2. Я так и сделал. Он возвращает объект JSON с соответствующими полями, но они все null . Я также получаю предупреждение, но я не могу сказать, актуально ли это: QueryResult interface method toString doesn't appear to be a getter and therefore may not return the correct result.

Ответ №1:

  1. Вам нужен @QueryResult в вашем интерфейсе
  2. Используемый вами запрос не будет работать с SDN (spring data neo4j), он нуждается в небольшой модификации при возврате результата, как показано ниже @Query(«СОПОСТАВЬТЕ (n: Person ) ГДЕ n. is_man = true С n ВОЗВРАЩАЙТЕ ID (n) как id,n.first_name как FirstName, n.is_man как isMan»)

Тогда это сработает. Ниже приведен пример, который отлично работает

  @QueryResult
public interface PersonProjection {
    String getName();
}
  public interface PersonRepository extends Neo4jRepository<Person, Long> {

   
    @Query("MATCH (pr:Person) return pr.name as name")
    public List<PersonProjection> getPersonWithAllFriends();

   

}