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

时间:2010-01-11 10:54:44

标签: java hibernate jpa eclipselink

这是同样的问题:

How to dynamically generate SQL query based on user's selections?

唯一的区别是,我对使用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))

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

5 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

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

在Toplink中,我们获得了Expression, and ExpressionBuilder

答案 2 :(得分:1)

如果要在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")
                }
            )

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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

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

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