You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JDBC不支持Query by Example,可用什么方案替代?

解决方案

Spring Data JDBC本身没有内置Query By Example能力,可通过以下3种方案实现相同的动态等值查询效果:

方案1:集成Querydsl(最接近QBE的官方推荐方案)

Querydsl支持动态生成类型安全的查询,是Spring Data JDBC官方推荐的动态查询实现方式。

实现步骤:

  • 引入Querydsl依赖,配置APT处理器自动生成查询实体类(Q类)
<!-- pom.xml 依赖配置 -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-relational</artifactId>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-sql</artifactId>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <scope>provided</scope>
</dependency>
  • 让OrderRepository继承QuerydslPredicateExecutor接口
public interface OrderRepository extends CrudRepository<Order, Long>, QuerydslPredicateExecutor<Order> {
}
  • 动态拼接查询条件后执行查询
import com.querydsl.core.BooleanBuilder;
import com.example.entity.QOrder;

// 从JSON转换得到的Order实体
Order orderFromJson = ...;
QOrder qOrder = QOrder.order;
BooleanBuilder predicate = new BooleanBuilder();

// 逐个判断字段非空就加入查询条件
if (orderFromJson.getSomeField1() != null) {
    predicate.and(qOrder.someField1.eq(orderFromJson.getSomeField1()));
}
if (orderFromJson.getSomeField2() != null) {
    predicate.and(qOrder.someField2.eq(orderFromJson.getSomeField2()));
}
// 其余字段逻辑同理,字段较多时可通过反射批量判空组装条件

// 执行查询返回结果
Iterable<Order> orders = orderRepository.findAll(predicate);

方案2:@Query + SpEL动态条件(适合简单轻量场景)

如果不想引入额外依赖,可以用SpEL表达式在注解SQL里动态判断字段是否为空,为空就自动忽略该条件:

public interface OrderRepository extends CrudRepository<Order, Long> {
    @Query("""
        SELECT * FROM order 
        WHERE (:#{#order.someField1} IS NULL OR some_field1 = :#{#order.someField1})
        AND (:#{#order.someField2} IS NULL OR some_field2 = :#{#order.someField2})
        AND (:#{#order.someField3} IS NULL OR some_field3 = :#{#order.someField3})
        AND (:#{#order.someField4} IS NULL OR some_field4 = :#{#order.someField4})
    """, nativeQuery = true)
    List<Order> findAllByDynamicFilter(@Param("order") Order order);
}

调用时直接传入从JSON转换得到的Order实体即可,null值字段对应的查询条件会自动失效。

方案3:JdbcTemplate手动拼接SQL(灵活度最高)

如果查询规则非常复杂,可以直接用JdbcTemplate动态拼接SQL和参数:

@Repository
public class DynamicOrderRepository {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<Order> findByFilters(Order filter) {
        StringBuilder sql = new StringBuilder("SELECT * FROM order WHERE 1=1 ");
        List<Object> params = new ArrayList<>();

        if (filter.getSomeField1() != null) {
            sql.append("AND some_field1 = ? ");
            params.add(filter.getSomeField1());
        }
        if (filter.getSomeField2() != null) {
            sql.append("AND some_field2 = ? ");
            params.add(filter.getSomeField2());
        }
        // 其余字段逻辑同理

        return jdbcTemplate.query(sql.toString(), params.toArray(),
                BeanPropertyRowMapper.newInstance(Order.class));
    }
}

内容的提问来源于stack exchange,提问作者DozezQuest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 03:21:03