【问题标题】:Dynamic amount of parameters in where clausewhere 子句中参数的动态数量
【发布时间】:2018-10-29 20:41:22
【问题描述】:

一开始我需要说,我尝试这样做的方式可能很愚蠢,但这只是我想出来的一个。

我有汽车属性表,有一次我需要通过一个参数获取日期 { “标记”:“奥迪” }

其他时候我需要更具体的 { “标记”:“奥迪”, “型号”:“A4” }

所以我写方法

    public List<Object> findVehicleProperty(String propertyType, Vehicle vehicle) {
    String queryParam = "";

    if(vehicle.getMark() != null) queryParam += "mark='"+vehicle.getMark()+"'&";
    if(vehicle.getModel() != null) queryParam += "model='"+vehicle.getModel()+"'&";
    if(vehicle.getEnginePower() != null) queryParam += "engine_power="+vehicle.getEnginePower()+"&";
    if(vehicle.getSeatCount() != null) queryParam += "seat_count="+vehicle.getSeatCount()+"&";
    if(vehicle.getDoorsCount() != null) queryParam += "doors_count="+vehicle.getDoorsCount()+"&";
    if(vehicle.getGearboxCount() != null) queryParam += "gearbox_count="+vehicle.getGearboxCount()+"&";
    if(vehicle.getType() != null) queryParam += "type="+vehicle.getType()+"&";


    //remove last "&" mark
    if (queryParam.length() > 0) {
        queryParam = queryParam.substring(0, queryParam.length() - 1);
    }


    return vehicleRepository.getParameters(queryParam);
}

从 sql "mark=Audi&model=A4 返回 WHERE 子句,然后我尝试将这部分 sql 作为参数传递给 Repository

@Query(value = "select * from Vehicle where ?1", nativeQuery = true)
List<Object> getParameters(String query);

我安慰我可以看到它很好地交互

2018-10-29 21:35:57.488 DEBUG 6240 --- [nio-8080-exec-1] org.hibernate.SQL                        : select * from Vehicle where ?

2018-10-29 21:35:57.494 TRACE 6240 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [mark='Audi'&model='A4']

但是这个请求总是返回空集合,如果我直接在 DB 上使用 select * from Vehicle where mark='Audi'&model='A4' 我会得到正确的结果。

你知道为什么吗?

【问题讨论】:

  • 您正在处理 SQL 而不是 url 查询参数。应该是mark=Audi AND model=A4。
  • 有趣的是,他没有得到 SQL 语法错误 ;)
  • 它很可能正在搜索 Audi&amp;model=A4 的汽车标记。
  • 这不是个案。仅通过 mark='Audi' 我仍然一无所获
  • @tsilakp 不,这也没有任何意义。

标签: java sql hibernate spring-boot


【解决方案1】:

你不能使用准备好的语句来“注入”整个 where 子句,因为它会转义你的“本机字符串”,所以你最终会得到 ​​p>

SELECT * FROM whatever WHERE '123456'

或类似的东西。

对于动态标准(即您的情况),请使用CriteriaAPI,因此CriteriaBuilder 将成为您的朋友。

【讨论】:

  • 非常感谢。我使用您的建议来使用 Criteria API 并按照我的预期工作
【解决方案2】:

在 SQL 术语中建议是 COALESCE。

不确定这是否会在春季使用

在你的情况下,它可以像这样工作:

SELECT * 
FROM Vehicle 
WHERE COALESCE(mark = :mark, true) and 
      COALESCE(model = :model, true)  and   
      COALESCE(engine_power = :engine_power, true) and 
      COALESCE(seat_count = :seat_count, true) and 
      COALESCE(doors_count = :doors_count, true) and 
      COALESCE(gearbox_count = :gearbox_count, true) and 
      COALESCE(type = :type, true) ;

这建议您将所有可能的参数作为" and COALESCE(attribute = :attribute , true)" or " and COALESCE(attribute= ?1 , true)"

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多