使用querydsl-jpa / querydsl-sql

时间:2015-07-10 12:53:33

标签: jpql querydsl

我正在尝试使用QueryDSL计算平均日期差异。

我创建a small project以简化的方式演示我想要完成的事情(真正的查询要复杂得多,有大量的连接/ where / sort子句)。我们有一个Customer类,其中birthDate字段,我们正在尝试获取客户的平均年龄(以秒为单位)。我们也想要最大年龄,但让我们关注这篇文章的平均值。

I tried writing this query using querydsl-jpa,但它失败并出现了一个模糊的错误:

java.lang.NullPointerException
        at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$AvgFunction.determineJdbcTypeCode(StandardAnsiSqlAggregationFunctions.java:106)
        at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$AvgFunction.render(StandardAnsiSqlAggregationFunctions.java:100)
        at org.hibernate.hql.internal.ast.SqlGenerator.endFunctionTemplate(SqlGenerator.java:233)
        [...]

我也尝试过其他方法,例如使用NumberTemplate.create(Double.class, "{0} - {1}", DateExpression.currentDate(), customer.birthDate).avg(),但它没有返回正确的值。如果我们想要以秒为单位获得日期差异,我们似乎需要找到一些方法来调用特定于数据库的日期/时间差异函数,而不仅仅是使用减号。

可悲的是,computing a date difference doesn't seem to be possible in JPQL,所以我猜querydsl-jpa也有局限性。因此,我们必须编写本机SQL查询,或者发现一些hack让QueryDsl生成的JPQL调用本机数据库函数。

JPA 2.1 added support for invoking database functions,但是有一个问题:MySQL函数采用TIMESTAMPDIFF(SECOND, '2012-06-06 13:13:55', '2012-06-06 15:20:18')形式。如果第一个参数(SECOND)是一个String,它可能是可能的,但它似乎是对某种常量的引用,并且在第一个参数未引用的情况下生成JPQL似乎很复杂。

QueryDSL added support for date differences,但似乎大多数代码都存在于querydsl-sql项目中,所以我想知道我是否可以通过querydsl-jpa从中受益。

以下是我的问题:

  1. 是否可以使用querydsl-jpa计算平均日期差异,让它可以使用JPA 2.1支持调用本机数据库函数(可能使用Expressions.numberTemplate())?或者我们被迫使用querydsl-sql?

  2. 如果我们必须使用querydsl-sql,我们如何同时生成QCustomerSCustomerQCustomer目前使用插件“com.mysema.maven:apt-maven-plugin”从Customer实体生成。如果我理解正确,I have to use a different plugin(com.querydsl:querydsl-maven-plugin)生成SCustomer查询类型?

    在查看querydsl-sql-example时,我没有看到任何实体类,所以我猜查询类型是由QueryDSL从数据库模式生成的?有没有办法从实体生成SCustomer查询类型,就像我们使用querydsl-jpa一样?

  3. 如果我们使用querydsl-sql,有没有办法在querydsl-sql查询中“重用”我们的querydsl-jpa谓词/ sorts / joins子句?或者我们是否必须使用特定于querydsl-sql的类复制该代码?

  4. 我也在考虑创建一个委托给TIMESTAMPDIFF(SECOND, x, y)的数据库函数,但它不是很便携......

  5. 我错过了什么吗?有没有更简单的方法来做我想做的事情?

1 个答案:

答案 0 :(得分:1)

使用模板表达式,您应该能够将任何自定义JPQL片段注入Querydsl查询。这应该回答你的第一个问题。

在同一个项目中使用querydsl-jpa和querydsl-sql是可能的,但会增加一些复杂性。