我尝试获取看起来像这样的查询:
select count(*) from somewhere group by DATEDIFF(week, '2010-01-01', creation_date);
我的问题是在功能调用上。我正在使用下面的Hibernate的JPA Criteriabuilder(CB)(root是我的某个地方):
cb.function("DATEDIFF", Integer.class, cb.literal("week"), cb.literal('2010-01-01'), root.<Date>get("creationDate")
生成的SQL是:
select count(*) from somewhere group by DATEDIFF(?, ?, creation_date);
- param1: 'week'
- param2: '2010-01-01'
哪个不起作用,因为第一个函数参数应该是常数而不是"?"。
我该如何像这样注入这个常数参数(没有引号,不是参数)?
谢谢
在这种情况下我的对象类似:
@Entity
public class Somewhere {
@Id
private Long id;
@Column(nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
// Getters and setters
}
基于基督教评论,解决方案实际上很容易实现。
SQL Server方言带有新功能'WeekDiff':
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.type.StandardBasicTypes;
public class ExtendedSqlServerDialect extends SQLServerDialect {
public ExtendedSqlServerDialect() {
registerFunction("weekdiff", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "datediff(week, ?2, ?1)"));
}
}
然后,只需要要求Hibernate使用此方言(我正在使用Spring Boot)。
application.yml :
spring.jpa.properties.hibernate.dialect: com.xxx.dialect.ExtendedSqlServerDialect
和代码示例我在哪里使用:
CriteriaBuilder cb /* = ... */;
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<Upload> root = query.from(Somewhere.class);
query.groupBy(cb.function("weekdiff",
Integer.class,
root.get("creationDate"),
cb.parameter(String.class, "refDate")).alias("week")
);
并且由于我在单元测试上使用了HSQLDB,因此在这里对应 HSQLDB方言:
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.type.StandardBasicTypes;
public class ExtendedHsqlDialect extends SQLServerDialect {
public ExtendedHsqlDialect() {
registerFunction("weekdiff", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "truncate(datediff('day', ?2, ?1) / 7)"));
}
}
不幸的是,我无法通过子句在组上使用此功能(请参阅"为什么约会订单"使用JPA在SQL Server上提出异常?)