Как отсортировать список сущностей на имущество из коллекции сущностей - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть сущность Mission, у которой есть коллекция сущностей Trip, и я хотел бы иметь возможность отсортировать миссию по функциям содержимого в коллекции Trip.

Сущность Trip:

@Entity
public Class Trip {
    @Id private Long id;
    @Column private LocalDateTime time;
}

Сущность Mission:

@Entity
public Class Mission {
    @Id private Long id;
    @Column private String city;
    @OneToMany(mappedBy = "mission")
    private Collection<Trip> trips;
}

Хранилище Mission:

@Repository
public interface MissionRepository extends PagingAndSortingRepository<Mission, Long>, QuerydslPredicateExecutor<Mission>, QuerydslBinderCustomizer<QMission> {

    @Override
    default void customize(final QuerydslBindings bindings, final QMission mission) {
        bindings.bind(String.class).first((final StringPath path, final String value) -> path.containsIgnoreCase(value));
        bindings.including(mission.city);
        bindings.excludeUnlistedProperties(true);
    }

    Page<T> findAll(Predicate predicate, Pageable pageable);
}

Mission Сервис:

@Service
@Transactional
public class MissionService {

    private final MissionRepository missionRepository;

    @Autowired
    public MissionService(final MissionRepository missionRepository) {
        this.missionRepository = missionRepository;
    }

    public Page<Mission> findAll(final Predicate predicate, final Pageable pageable) {
        return this.missionRepository.findAll(predicate, pageable);
    }
}

Контроллер Mission:

@RestController
@RequestMapping("/api/missions")
public class MissionController {

    private final MissionService missionService;

    @Autowired
    public MissionController(final MissionService missionService) {
        this.missionService = missionService;
    }

    @GetMapping
    @ResponseBody
    public Page<Mission> getAllMissions(@QuerydslPredicate(root = Mission.class) final Predicate predicate, @PageableDefault final Pageable pageable) {
        return this.missionService.findAll(predicate, pageable);
    }
}

При вызове /api/missions?sort=city,DESC он работает отлично.Но при звонке /api/missions?sort=trips.time,DESC я получаю дубликаты записей, которые соответствуют количеству поездок, связанных с миссией.Все эти миссии правильно отсортированы, но повторяющаяся часть просто не нужна ...

Цель состоит в том, чтобы иметь возможность сортировать Mission (ASC или DESC) в зависимости от даты отъездаиз коллекции Trip (которая будет первой Trip, отсортированной в ASC).

Итак, как отсортировать этот список Mission для содержимого из коллекции Trip безполучить дублирующую часть?

Я также хотел бы по возможности избежать изменения сигнатуры метода REST или структуры базы данных.

Я думал о добавлении DISTINCT в список, ноЭто не сработает, поскольку сортировка должна выполняться в поле времени первой поездки.Сортировка в режиме ASC будет работать.Но в DESC он будет отсортирован в зависимости от даты прибытия, а не отбытия…

Сумасшедшая идея: можно ли будет автоматически заполнить переходное свойство в миссии содержимымзапрос и сортировка по нему с использованием класса Pageable?

1 Ответ

0 голосов
/ 29 ноября 2018

1 - первая опция

Мне удалось исправить проблему с помощью аннотации @Formula из Hibernate.

1.1 - добавление следующего свойства внутри Mission сущности

@Formula("(select min(t.time) from Trip t where t.mission_id = id)")
private LocalDateTime startDate;

1.2 - Сортировка по свойству

Нам просто нужно вызвать свойство.

/api/missions?sort=startDate,DESC.


2 - Второй вариант

В настоящее время у меня нет проблем с производительностью.Тем не менее, на всякий случай, я также рассматриваю возможность использования представления, которое затем будет связано с моей сущностью.

Примечание: это не было тестом, но оно основано на моем понимании из следующего blog .

2.1 - Создание представления на основе таблиц Trip и Mission

CREATE OR REPLACE VIEW mission_derived AS
select 
  m.`id` as id,
  min(t.`time`) as startDate
from `trip` t
inner join `mission` m on t.`mission_id` = m.`id`
group by m.`id`;

2.2 - Создание объекта Java, соответствующего этому представлению

@Entity
@Immutable
public class MissionDerived {

  @Id
  private long id;

  @Column
  private Date startDate;

}

2.3 - Добавление свойства в мою Mission сущность

@OneToOne
@PrimaryKeyJoinColumn(name="ID")
private MissionDerived derived;

2.4 - Сортировка с использованием этого свойства

Затем нам потребуется вызвать свойство измиссия, а затем имущество от производного лица.

/api/missions?sort=derived.startDate,DESC

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...