Spring Boot Querydsl: сортировка - иногда не работает для указанного атрибута enitity c - PullRequest
0 голосов
/ 29 января 2020

Я создаю хранилище данных с помощью Spring Boot и Angular. Для некоторых таблиц мне нужна комбинация поиска, фильтрации, (мульти) сортировки и просмотра страниц. Поэтому я использую Querydsl, он идеально соответствует моим потребностям. Но у меня есть некоторые проблемы с этим. После создания приложения Java сортировка иногда не работает для некоторых атрибутов моего объекта. Отладка показала, что параметр sorting в pageable равен UNSORTED для этих указанных атрибутов.

Чтобы сделать это более понятным, я покажу некоторый код. Объект:

Entity
@Table(name = "ExternalEffortLinkManagement", schema = "dbo")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "externalEffortLinkManagementId")
public class ExternalEffortLinkManagement {

    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    @Column(name = "ExternalEffortLinkManagement_ID")
    private long externalEffortLinkManagementId;

    @Column(name = "Mitarbeiter")
    private String employee;

    @Column(name = "Jahr")
    private int year;

    @Column(name = "Monat")
    private int month;

    @Column(name = "Projektnummer")
    private String projectNumber;

    @Column(name = "InitialMailSent")
    private Timestamp initialMailSent;

    @Column(name = "LastReminderSent")
    private Timestamp lastReminderSent;

    @Column(name = "Active")
    private boolean active;

Метод в контроллере:

    @RequestMapping(value = EXTERNAL_EFFORT_LINK_MANAGEMENT_URL + "/advancedSearch", method = RequestMethod.GET)
    @ResponseBody
    public PagedResources<ExternalEffortLinkManagement> advancedSearch(
            @RequestParam(value = "search", required = false) String search,
            Pageable pageable, @RequestParam MultiValueMap<String, String> parameters,
            PersistentEntityResourceAssembler persistentEntityResourceAssembler
    ) {
        SimpleGrantedAuthority[] allowedRoles = {SYSADMIN, SUBCONTRACTOR_MANAGEMENT}; // <-- Debug point was here

        GeneralPredicateBuilder<ExternalEffortLinkManagement> builder = new GeneralPredicateBuilder<ExternalEffortLinkManagement>(ExternalEffortLinkManagement.class);
        Predicate predicate = predicateService.getPredicateFromParameters(parameters, ExternalEffortLinkManagement.class);
        Page<ExternalEffortLinkManagement> results = service.advancedSearch(
                this.buildAdvancedSearch(search, predicate, builder), pageable, allowedRoles);
        return super.toPagedResource(results, persistentEntityResourceAssembler);
    }

Репозиторий:

@CrossOrigin(exposedHeaders="Access-Control-Allow-Origin")
@RepositoryRestResource(collectionResourceRel = EXTERNAL_EFFORT_LINK_MANAGEMENT_URL, path = EXTERNAL_EFFORT_LINK_MANAGEMENT_URL)
public interface ExternalEffortLinkManagementRepositoryExtEff extends PagingAndSortingRepository<ExternalEffortLinkManagement, Long>, JpaSpecificationExecutor<ExternalEffortLinkManagement>, QuerydslPredicateExecutor<ExternalEffortLinkManagement> {

};

Метод обслуживания:

    public Page<ExternalEffortLinkManagement> advancedSearch(Predicate predicate, Pageable pageable, SimpleGrantedAuthority[] roles){
        if (SecurityUtils.userHasAnyRole(roles)) {
            return this.calcSumHours(this.repository.findAll(predicate, pageable));
        } else throw new ForbiddenException(FORBIDDEN);
    }

Теперь, когда вы увидели код, позвольте мне четко объяснить поведение.

  1. Сначала я запускаю gradle clean, затем gradle build и затем приложение. После этого я делаю запрос (не имеет значения, делаю ли я это из приложения или прямо в браузере или в Postman et c., Результат тот же) advancedSearch?page=0&size=10&sort=employee,asc&sort=active,asc&month=1&year=2020. Все отлично, результаты сначала сортируются по employee, а затем по active.

  2. Теперь я останавливаю приложение, gradle build, запускаю приложение. При повторном выполнении запроса employee игнорируется при сортировке, результаты сортируются только по флажку active.

  3. Теперь я снова останавливаю приложение, gradle build, запускаю приложение. Делая запрос снова, все работает. Я не бегал clean! И я ничего не изменил в исходном коде.

  4. Теперь, опять в четвертый раз, я останавливаю приложение, gradle build, запускаю приложение. При повторном выполнении запроса employee игнорируется при сортировке, результаты сортируются только по флажку active. После четвертой сборки я больше не работаю, пока не введу команду clean.

Чтобы сделать его более сложным, чем он есть, поведение аналогично для некоторых из атрибуты объекта. Не имеет значения, комбинирую ли я параметры сортировки или просто использую их.

  • employee: иногда работает
  • projectNumber: иногда работает
  • initialMailSent, lastReminderSent, active: работает всегда (также в

Когда сотрудник не working, projectNumber также не работает, с другой стороны, если один работает, другой также работает.

Фильтры (month, year) всегда одинаковы и не влияют на поведение.

Querdsl генерирует некоторые классы, поэтому я подумал, что эти классы могут вызвать проблему. Но это не так, потому что у меня почти такая же проблема в цепочке непрерывной интеграции, там происходит переключение между работой в первой сборке, не работой во второй, работой в третьей и так далее. Так что просто шаги 2 и 3. В цепочке сборка всегда начинается с чистого кода (без сгенерированных классов, они были сгенерированы во время сборки).

У кого-нибудь есть такая же проблема и лучшее объяснение и решение?

1 Ответ

0 голосов
/ 30 января 2020

После нескольких часов поиска я наконец обнаружил проблему.

У нас был какой-то "старый" класс сущностей ExternalEffortLinkManagement с почти такими же атрибутами, но employee и projectNumber там, где их не было. Этот класс был помещен в другой пакет. Это объясняет, почему все остальные атрибуты всегда были приняты в качестве допустимых параметров сортировки, но не employee и projectNumber.

Это выглядит так, как java build смешивает эти два класса (старый и новый) , В настоящее время я не понимаю, почему сборки используют иногда новый класс, а иногда старый.

Но удаление старого класса устранило проблему. Я все еще думаю, что несоответствие между сборками должно быть ошибкой в ​​компиляторе или чем-то подобным, потому что для меня это не имеет смысла, что иногда используется class a from package a, а иногда class a form package b.

...