我有一个实体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
,但是由于排序需要在第一个Trip的时间字段中进行,因此无法正常工作。可以在ASC
模式下进行排序。但是在DESC
中,它将根据到达日期而不是出发日期进行排序...
一个疯狂的想法:是否有可能自动使用查询的内容填充任务中的瞬时属性,然后使用Pageable
类对其进行排序?
答案 0 :(得分:0)
我可以使用Hibernate的@Formula
注释解决问题。
Mission
实体内添加以下属性@Formula("(select min(t.time) from Trip t where t.mission_id = id)")
private LocalDateTime startDate;
我们只需要调用属性即可。
/api/missions?sort=startDate,DESC
。
目前,我没有任何性能问题。 但是,以防万一,我还考虑使用一个视图,然后将其链接到我的实体。
注意:这不是一个测试,但基于我对以下blog的理解。
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`;
@Entity
@Immutable
public class MissionDerived {
@Id
private long id;
@Column
private Date startDate;
}
Mission
实体@OneToOne
@PrimaryKeyJoinColumn(name="ID")
private MissionDerived derived;
然后,我们需要从任务中调用属性,然后从派生实体中调用属性。
/api/missions?sort=derived.startDate,DESC