简体   繁体   English

从用户搜索条件动态创建WHERE子句

[英]Dynamic create WHERE clause from user Search criteria

I have what I'm sure is a fairly common issue, and I don't want to re-invent the wheel. 我有一个我确定是一个相当普遍的问题,我不想重新发明轮子。 I have a search form where users can specify search criteria and type of search (AND OR Ext..). 我有一个搜索表单,用户可以在其中指定搜索条件和搜索类型(AND OR Ext ..)。

The form passes back id's that map to column names and values. 表单传回id映射到列名和值的id。 Currently, I'm using server side Java to glue the strings together into a where clause. 目前,我正在使用服务器端Java将字符串粘合到一个where子句中。 It works in some cases, but it's clunky, error prone and will not scale well. 它在某些情况下有效,但它很笨重,容易出错并且不能很好地扩展。

Any suggestions? 有什么建议么?

Thanks, 谢谢,

David 大卫

If you were using an ORM (I use Hibernate), you could use the Criteria API: it lets you agregate conditions (using a loop for example), and builds the resulting query. 如果您使用的是ORM(我使用的是Hibernate),您可以使用Criteria API:它可以让您重新聚合条件(例如使用循环),并构建生成的查询。

In native SQL, I don't know a library that would do that. 在本机SQL中,我不知道会这样做的库。 Maybe you could write your own, getting some inspiration from the documentation and code for Hibernate Criteria ? 也许你可以编写自己的,从Hibernate Criteria的文档和代码中获得一些灵感?


OR: 要么:

If you do something sufficiently complex on the client (say you manage priorities between AND and OR, you can nest conditions using parenthesis ...), then you're probably already building a data structure that handles this on the client. 如果你在客户端做了一些足够复杂的事情(比如你管理AND和OR之间的优先级,你可以使用括号嵌套条件......),那么你可能已经构建了一个在客户端处理这个问题的数据结构

In that case, I suggest you send that data structure to the server, and use it via loops to build your query. 在这种情况下,我建议您将该数据结构发送到服务器,并通过循环使用它来构建您的查询。

I'd use prepare and ? 我用准备和? for parameters anyway, if only to avoid injection and other misconversion risks. 无论如何,如果只是为了避免注入和其他误转换风险。

If your search criteria are limited in size, you can statically list all possible queries to prepare. 如果搜索条件的大小有限,您可以静态列出要准备的所有可能的查询。

If not, you can maintain a pool of prepared queries dynamically. 如果没有,您可以动态维护准备好的查询池。 This is not as useful for a web app, where you probably won't get to reuse any of the queries you prepare. 这对于Web应用程序没有用处,您可能无法重用您准备的任何查询。

You have to build the search string either on the client or on the server. 您必须在客户端或服务器上构建搜索字符串。 Building it on the client is obviously not a good solution (security-wise), so the only option is to build it on the server. 在客户端上构建它显然不是一个好的解决方案(安全方面),因此唯一的选择是在服务器上构建它。 Personally, I would use or build a Searcher object, which handles the recurring task of building search strings effeciently and creates a Statement from there. 就个人而言,我会使用或构建一个Searcher对象,它可以有效地处理构建搜索字符串的重复任务,并从那里创建一个Statement。

Hibernate has a Criteria API which allows to create dynamic queries using only method invocation, with no need for manual composition of the sql query. Hibernate有一个Criteria API,它允许仅使用方法调用创建动态查询,而无需手动组成sql查询。

But you should consider using a solution for full text search like Lucene or Hibernate Search, which greatly reduce the need for queries with complex condition. 但是你应该考虑使用像Lucene或Hibernate Search这样的全文搜索解决方案,这大大减少了对复杂条件查询的需求。 Full text search is also a much better solution for the user experience, as a full text search is simpler to perform and usually provides better results. 全文搜索也是一种更好的用户体验解决方案,因为全文搜索更容易执行,通常可以提供更好的结果。

Massimiliano Fliri's suggestion to look at the Criteria API got me headed in the right direction. Massimiliano Fliri建议看看Criteria API让我朝着正确的方向前进。 I stopped thing about building "just a where clause" and started thinking about this as a need to build statements. 我停止了构建“只是一个where子句”的事情,并开始考虑将此作为构建语句的需要。

This lead me to a solution: Squiggle-sql: http://code.google.com/p/squiggle-sql/ 这引出了我的解决方案:Squiggle-sql: http//code.google.com/p/squiggle-sql/

From the docs: 来自文档:

Squiggle is a little Java library for dynamically generating SQL SELECT statements. Squiggle是一个用于动态生成SQL SELECT语句的小型Java库。 It's sweet spot is for applications that need to build up complicated queries with criteria that changes at runtime. 对于需要使用在运行时更改的条件构建复杂查询的应用程序来说,它的最佳点是。 Ordinarily it can be quite painful to figure out how to build this string. 通常,弄清楚如何构建这个字符串可能会非常痛苦。 Squiggle takes much of this pain away. Squiggle消除了很多痛苦。

If you are using Hibernate as ORM then use the Criteria api to do this. 如果您使用Hibernate作为ORM,那么使用Criteria api来执行此操作。 It must easier to add/remove clauses based on some conditions. 根据某些条件添加/删除子句必须更容易。

If you are building a jdbc query keep the part that is constant first and append the varying part for eg 如果要构建jdbc查询,请首先保持该常量的部分,并附加变量部分,例如

select * from trans where userid = ? select * from trans where userid =?

and append based on conditions eg 并根据条件附加,例如
if amount != null then append ' and amount > ? 如果金额!= null然后追加'和金额>? '

As long as you can keep the constant part well segregated from the varying part you should not have much problem. 只要你可以保持恒定部分与变化部分隔离良好,你就不会有太多问题。

The book "Expert SQL Server 2005 Development" by Adam Machanic has some excellent suggestions in chapter 7 concerning dynamic SQL. Adam Machanic的“Expert SQL Server 2005开发”一书在第7章中有关于动态SQL的一些很好的建议。 He dives into all kinds of issues including performance, maintainability, and security. 他潜入各种问题,包括性能,可维护性和安全性。 I won't attempt to rewrite his chapter - suffice to say that he believes less is more when it comes to SQL. 我不会试图重写他的章节 - 足以说他相信在SQL方面更少。

It's specific to SQL Server but I believe his general approach (huge where clause vs. if/then SQL vs. dynamic) can be applied across the board. 它是特定于SQL Server但我相信他的一般方法(巨大的where子句与if / then SQL与动态)可以全面应用。

EDIT: I think it's worthwhile to add... never trust input from the client, always parameterize your input before using it in SQL. 编辑:我认为值得添加...永远不要信任来自客户端的输入,在SQL中使用它之前总是参数化你的输入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM