如何在Spring Data中按数据库不存在的用户名字段对Vehicle排序?
解决Spring Data中Vehicle按Cognito用户名排序的问题
首先明确:SPEL在这里不可行,因为Spring Data的排序依赖实体字段或数据库列,而用户名仅存在Cognito服务中,不在本地数据库或实体的持久化字段里,SPEL无法直接调用Cognito接口获取数据用于排序。
下面给你几个实用的解决方案:
方案一:内存中排序(适合数据量小的场景)
在Vehicle实体中添加一个非持久化的用户名字段,查询后填充Cognito数据再排序:
- 修改Vehicle实体,添加
@Transient字段存储用户名:
class Vehicle(id: UUID, name: String, updatedBy: User) { @Transient var username: String? = null }
- 从仓库获取Vehicle列表后,批量调用Cognito接口获取所有关联用户ID对应的用户名,批量填充到Vehicle的
username字段(批量调用比逐个调用更高效)。 - 用Java Stream或Collections工具类完成排序:
val vehicles = vehicleRepository.findAll() // 批量获取userIds对应的用户名,用Map<UUID, String>存储结果 val usernameMap = cognitoService.getUsernamesByIds(vehicles.map { it.updatedBy.id }) vehicles.forEach { it.username = usernameMap[it.updatedBy.id] } // 按用户名排序 val sortedVehicles = vehicles.sortedBy { it.username }
方案二:冗余用户名到数据库(推荐,适合频繁排序场景)
如果业务允许,把Cognito的用户名同步到本地数据库的冗余字段中,这样就能直接用Spring Data的原生排序功能:
- 给Vehicle实体添加持久化的
updatedByUsername字段:
class Vehicle( id: UUID, name: String, updatedBy: User, @Column(name = "updated_by_username") var updatedByUsername: String? = null )
- 在创建/更新Vehicle时,先通过Cognito获取当前用户的用户名,设置到
updatedByUsername字段再保存。 - 仓库中直接使用Spring Data的Sort进行排序:
interface VehicleRepository : JpaRepository<Vehicle, UUID> { // 直接按冗余字段排序 fun findAll(sort: Sort): List<Vehicle> } // 使用时 val sortedVehicles = vehicleRepository.findAll(Sort.by(Sort.Direction.ASC, "updatedByUsername"))
方案三:分页场景下的折中处理
如果需要分页+排序,先分页查询Vehicle数据,再批量获取用户名并排序(分页后数据量小,内存排序开销可接受):
// 先分页查询Vehicle val pageable = PageRequest.of(pageNum, pageSize) val vehiclePage = vehicleRepository.findAll(pageable) // 批量获取用户名 val usernameMap = cognitoService.getUsernamesByIds(vehiclePage.content.map { it.updatedBy.id }) // 填充并排序当前页的数据 val sortedContent = vehiclePage.content .onEach { it.username = usernameMap[it.updatedBy.id] } .sortedBy { it.username } // 构建新的Page对象返回 val sortedPage = PageImpl(sortedContent, pageable, vehiclePage.totalElements)
内容的提问来源于stack exchange,提问作者andrejuly
相关产品推荐
相关产品推荐

