Query DSL是否支持JPA projections?是否有可行的替代实现方案?
问题解答
特性支持说明
Querydsl JPA 5.0及以上版本已原生支持该特性,低于5.0的版本暂无官方支持计划,建议优先升级到5.x及以上版本使用原生支持能力。
通用变通解决方案(全版本可用)
方案1:手动通过
Projections类构造投影映射
这是兼容性最强的方案,不需要升级依赖,只需自定义Repository实现层编写查询逻辑,示例代码如下:import com.querydsl.core.types.Projections import com.querydsl.jpa.impl.JPAQueryFactory // 自定义Repository实现 class OrderRepositoryImpl( private val queryFactory: JPAQueryFactory ) : OrderRepositoryCustom { private val qOrder = QOrder.order override fun findAll(predicate: Predicate): Set<OrderView> { return queryFactory.select( Projections.fields( OrderView::class.java, qOrder.id, qOrder.orderNo, qOrder.createTime // 其他需要映射到OrderView的字段,字段名需和OrderView的属性名一致 ) ) .from(qOrder) .where(predicate) .fetch() .toSet() } }如果
OrderView是接口类型,将Projections.fields替换为Projections.interfaceBased即可;如果是DTO类且有全参构造函数,也可以用Projections.constructor实现构造器注入映射。方案2:结合Spring Data JPA的
@Query注解实现
如果你使用Spring Data JPA框架,可以直接在Repository接口中通过SpEL注入Predicate,无需编写自定义实现类,示例代码如下:interface OrderRepository : JpaRepository<Order, Long>, QuerydslPredicateExecutor<Order> { @Query("select o.id as id, o.orderNo as orderNo, o.createTime as createTime from Order o where #{#predicate}") fun findAllViews(predicate: Predicate): Set<OrderView> }
高版本原生用法(Querydsl 5.x+)
升级到对应版本后,无需额外编写映射逻辑,直接在Repository接口中定义返回类型为OrderView的方法即可直接使用,示例代码如下:
fun findAll(predicate: Predicate): Set<OrderView>
注意事项
- 类投影需要保证属性名和实体查询的字段别名完全一致,且提供无参构造函数(使用
Projections.fields时)或者全参构造函数(使用Projections.constructor时) - 接口投影只需定义对应字段的getter方法即可,无需提供实现类
- 使用
@Query方案时需确保项目已开启Spring Data JPA的Querydsl支持
内容的提问来源于stack exchange,提问作者Rory Towler
相关产品推荐
相关产品推荐

