2

这与以下问题相同:

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

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

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

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

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

  • 年龄- 年龄可以给出:

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

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

  • 身高- 与年龄相似

示例查询:

没有给出标准:

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))

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

4

5 回答 5

3

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

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

于 2013-09-27T16:34:37.453 回答
1

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

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

于 2010-01-11T10:59:04.337 回答
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")
                }
            )
于 2010-02-04T20:59:11.977 回答
1

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

于 2011-11-10T16:56:41.250 回答
0

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

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

wherejoin()将对象数组转换为字符串数组,然后将元素与参数连接起来。

于 2010-01-11T11:06:14.260 回答