如何根据用户的选择动态生成SQL查询?

这是同一个问题:

如何根据用户的选择动态生成SQL查询?

唯一的区别是,我对使用Java / JPA(+可能是EclipseLink或Hibernate特定扩展)的解决方案感兴趣。

我需要创建一个GUI,用户可以使用该GUI选择几个属性,这些属性将用于查询数据库以查找合适的人员。 我正在寻找如何根据用户的选择动态生成数据库查询的想法。

查询将包含几个字段,但为了得到这个想法,我将仅包括下面的三个作为示例:

  • 职业 – 可以有0到n个职业字符串。 如果给出了占用字符串,则其中一个必须匹配。

  • 年龄 – 年龄可以给出:

    1. 完全匹配(30)
    2. 范围(例如30-40)
    3. 小于一个值(-40)
    4. 超过一个值(30-)

Age参数在查询中是可选的。 此外,用户可以指定年龄是否为必需参数。 如果不是必需的,并且没有年龄的人是他/她的个人资料,则此人的年龄标准将被忽略。

  • 身高 – 与年龄相似

示例查询:

没有给出任何标准:

select * from persons 

只有职业:

 select * from persons where occupation = 'dentist' 

已经举办了几项职业:

 select * from persons where (occupation = 'dentist' or occupation = 'engineer') 

年龄已被赋予大于值,并且需要存在于个人的个人资料中:

 select * from persons where age >= 30 

高度已作为范围给出,并且不需要存在于人员的个人资料中:

 select * from persons where (height is null or (height >= 30 and height <= 40)) 

不同标准的组合:

 select * from persons where occupation = 'dentist' and age >= 30 and (height is null or (height >= 30 and height <= 40)) 

我已经实现了能够以字符串forms生成查询的代码,但它确实不太漂亮。 我正在寻找能够实现这一目标的最有效和最美妙的方法。

在Hibernate中,您可以使用Criteria查询。

在Toplink中,我们得到了Expression和ExpressionBuilder 。

有很多不同的工具,我认为最好是querydsl , torpedoquery e Object Query ,这三个允许编写类型安全查询,否则你可以使用条件api,如果你使用jpa 2也可以使用JPA2 Typesafe Query 。

使用所有这些工具,您可以在运行时构建查询!

如果要在JPA 1.X中执行此操作,可以使用http://rrusin.blogspot.com/2010/02/jpa-query-builder.html中所述的自定义查询构建器。 这样可以创建如下查询:

 return new JpaQueryBuilder().buildQuery(em, new Object[] { "select c from Car c where c.name is not null", new JQBParam("name", name, " and c.name = :name"), new JQBParam("type", type, " and c.type = :type") } ) 

我使用Querydsl框架,因为我使用的是JPA 1.0,它不包含Criteria API,我还需要你描述的function。 编写Querydsl代码很简单,代码比Criteria API代码短。 Querydsl是免费使用的,它支持类型安全查询。

在我的代码中,我正在使用ANDOR对象。 它们将列表作为参数(使用Java 5的可变参数看起来很好),并在字符串中将它们与必要的空格和括号连接起来。 伪代码:

 AND(WhereCond ... conds) { this.conds = conds; } toString() { return conds.length == 0 ? "" : "(" + join(conds, " AND ") + ")" }; 

其中join()将对象数组转换为字符串数组,然后使用参数连接元素。