Как выполнять запросы к иерархическим объектам, используя спецификации jpa querydsl или spring data? - PullRequest
4 голосов
/ 21 февраля 2020

У меня иерархия сущностей , подобная этой. Помимо некоторых общих свойств, некоторые свойства разделяются только несколькими подтипами:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Person {
    private String firstName;
    private String lastName

    ... further properties, getters and setters...
}

@Entity
public class Employee extends Person {
    private String salary;

    ... further properties, getters and setters...
}

@Entity
public class BoardMember extends Person {
    private String salary;

    ... further properties, getters and setters...
}

@Entity
public class ExternalMember extends Person {
    private String clearanceLevel;

    ... further properties, getters and setters...
}

@Repository
public interface PersonRepository extends JpaRepository<Person, Long>, QuerydslPredicateExecutor<Person> {

}

Используя QueryDSL, я пытаюсь найти людей в зависимости от критериев фильтра Dynami c, таких как:

@Service
@Transactional
public class PersonService {

  @Autowired
  PersonRepository personRepository;

  public Page<Person> search(String firstName, String salary) {
    var searchCriterias = new BooleanBuilder();
    if (firstName != null) {
      searchCriterias.and(QPerson.firstName.eq(firstName));
    }
    if (salary != null) {
        searchCriterias.andAnyOf(
          QPerson.person.as(QEmployee.class).salary.eq(salary),
          QPerson.person.as(QBoardMember.class).salary.eq(salary),
        );
    }
    personRepository.findAll(searchCriterias);
  }
}

Это не совсем правильный путь, однако я получаю много ошибок, таких как "зарплата", а не член Person.

Каковы различные способы поиска для иерархических объектов? Я бы предпочел QueryDSL для безопасности типов, но решения, использующие Spring Data Specification, тоже подойдут.

edit: критерии поиска могут быть очень сложными, если использовать более 15 различных критериев поиска. Поэтому мне нужен программный подход c, чтобы сформулировать их.

1 Ответ

0 голосов
/ 28 февраля 2020

Мне не удалось воспроизвести ошибку «не участник», но мне удалось получить результат по вашему запросу.

После учебного пособия Baeldung и адаптации кода из вашего вопроса Мне удалось получить результат без ошибок. Здесь - пример проекта. Надеюсь, это поможет

import javax.persistence.*;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column
    private String firstName;

    @Column
    private String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public Person() {
    }
}
import javax.persistence.Column;
import javax.persistence.Entity;

@Entity
public class BoardMember extends Person {

    @Column
    private String salary;

    public BoardMember(String firstName, String lastName, String salary) {
        super(firstName, lastName);
        this.salary = salary;
    }

    public BoardMember() {
    }
}
@Service
@Transactional
public class PersonService {

    @Autowired
    PersonRepository personRepository;

    public List<Person> search(String firstName, String salary) {
        var searchCriterias = new BooleanBuilder();
        if (firstName != null) {
            searchCriterias.and(QPerson.person.firstName.eq(firstName));
        }
        if (salary != null) {
            searchCriterias.andAnyOf(
                    QPerson.person.as(QEmployee.class).salary.eq(salary),
                    QPerson.person.as(QBoardMember.class).salary.eq(salary)
            );
        }

        var result = new ArrayList<Person>();
        for (Person person : personRepository.findAll(searchCriterias)) {
            result.add(person);
        }
        return result;
    }
}
...