如何最好地使用Java和Spring处理动态查询参数

问题描述 投票:0回答:1

问题:

我有一个api端点,可以处理多个查询参数。它是使用Spring实现的,查询参数用于从postgres数据库查询数据,我使用JDBC模板进行查询。

我正在寻找一种成熟的查询生成器技术来解决我的问题。

示例:

一个简单的查询可能看起来像这样:

api/book?name=LOTR&cover=hardback

将查询参数添加到地图,并根据地图数据构建查询字符串:

String sqlQuery += (String) map.entrySet().stream()
            .map(entry -> entry.getKey() + "='" + entry.getValue() + "' AND ")
            .collect(Collectors.joining());

它不是最有效的,因为我必须始终从字符串中删除尾随的"AND"子句,但它可以工作。

但是,如果查询在哪里看起来像

api/book?name=LOTR&name=Ulysses&cover=hardback

现在添加了"OR"子句,上述代码无法处理。我可以看到自己很快进入了繁琐的字符串解析来创建SQL语句的领域。

因此,既然我已经提出了我的问题,我想知道是否有一种我可以使用的技术可以很好地处理此类问题?

我想避免在该项目中使用任何ORM,因此Hibernate和MyBatis完全没有问题。我看了一些JOOQ示例,但它们看起来与JDBC模板不兼容。

sql spring postgresql http query-parameters
1个回答
0
投票

对于像第一种情况这样的琐碎实现,您必须删除最后一个AND并在构建查询之后就有一个简单的技巧-在WHERE之后立即添加1 = 1,然后为每个WHERE谓词添加AND [COLUMN] = [VALUE ]。

注意:大多数数据库在执行之前都会优化WHERE子句中常量的使用,因此性能不会成为问题

/*
  select <columns> from <tables> where 1 = 1
  [dynamically built Where predicates will come here from following code] 
*/

String sqlQuery += (String) map.entrySet().stream()
    .map(entry -> "AND " + entry.getKey() + "='" + entry.getValue() + "'")
    .collect(Collectors.joining());

但是对于严肃的生产实现,您可能希望使用myBatis之类的框架,该框架使您可以对查询进行模板化,然后在运行时传递参数以构建最终查询。

您可以找到一个很好的教程here

/* An example */
<select id = "getName_Id_phone" parameterType = "Student" resultType = "Student">
   SELECT * FROM STUDENT    
   <where>
      <if test = "id != null">
         id = #{id}
      </if>
      <if test = "name != null">
         AND name LIKE #{name}
      </if>
   </where>     
</select>
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.