Java JPA标准API中订单的自定义SQL
我正在从不推荐的(不幸的)Hibernate标准API切换到JPA标准API。我们有一个自定义的Order(来自Hibernate)接口实现来重新定义为它生成的SQL。这种情况非常复杂,因为我们需要在子查询中使用一个巨大的SELECT。我们实现了接口的Java JPA标准API中订单的自定义SQL,java,hibernate,jpa,hibernate-criteria,criteria-api,Java,Hibernate,Jpa,Hibernate Criteria,Criteria Api,我正在从不推荐的(不幸的)Hibernate标准API切换到JPA标准API。我们有一个自定义的Order(来自Hibernate)接口实现来重新定义为它生成的SQL。这种情况非常复杂,因为我们需要在子查询中使用一个巨大的SELECT。我们实现了接口的toSqlString方法来返回这个巨大的SQL,我们需要一种方法将它迁移到JPA标准API 问题是:JPA CriteriaAPI中是否有方法重新定义生成的SQL?还是有一种奇怪的方式将Hibernate Order与JPA Criteria A
toSqlString
方法来返回这个巨大的SQL,我们需要一种方法将它迁移到JPA标准API
问题是:JPA CriteriaAPI中是否有方法重新定义生成的SQL?还是有一种奇怪的方式将Hibernate Order与JPA Criteria API一起使用
谢谢大家!
更新尽管@Tobias Liefke的建议非常有趣,但我的SQL变化太大,无法为每个SQL创建函数类。我尝试实现一个函数类,并将SQL作为参数传递到那里,但没有成功(呈现的SQL包含在单引号中,因此它作为参数发送到数据库,而不是作为生成的查询的一部分)您不能在JPQL或条件查询中使用SQL片段 。。。除非 1.调用函数 JPA和Hibernate允许在其表达式中使用函数,例如:
... ORDER BY trim(entity.label) ASC
分别
问题是,这实际上不是对SQL函数trim
的调用,而是对JPA函数的调用,必须注册该函数(Hibernate已经对最常见的SQL函数进行了注册)
幸运的是,您可以在方言解析器中定义自己的JPA函数:
public class MyDialectResolver implements DialectResolver {
public Dialect resolveDialect(final DialectResolutionInfo info) {
Dialect dialect = StandardDialectResolver.INSTANCE.resolve(info);
dialect.registerFunction("myOrderFunction", ...);
return dialect;
}
}
registerFunction
接受两个参数,第一个是JPA中函数的名称,另一个是到SQL的映射
不要忘记在persistence.xml中声明方言解析器:
<persistence-unit name="database">
<properties>
<property name="hibernate.dialect_resolvers"
value="my.package.MyDialectResolver" />
</properties>
</persistence-unit>
或者,您可以编写自己的映射,其中包括庞大的SQL:
并将其登记为:
dialect.registerFunction("myOrderFunction", new MyOrderFunction());
此解决方案的另一个优点是:可以根据实际的数据库方言定义不同的SQL
2.使用公式
您可以为实体使用其他属性:
@Formula("my huge SQL")
private String orderAttribute;
现在可以按此属性进行排序:
... ORDER BY entity.orderAttribute ASC
分别
我只推荐这种解决方案,如果您需要模型中庞大SQL的结果。否则,它只会污染实体模型,并将SQL添加到实体的每个查询中(除非您使用@Basic(fetch=FetchType.lazy)
标记它并使用字节码检测)
类似的解决方案是使用巨大的SQL定义一个@Subselect
实体,但也有同样的缺点。非常有趣,非常感谢!因此,我可以使用第一个解决方案,而不必在Oracle中创建实际的函数,也不必简单地实现SQLFunction接口,对吗?对。事实上,第一个解决方案包含两个“风格”:一个带有自定义SQL函数,另一个带有映射接口。太棒了!很好的解决方案,我想,在这种情况下是最好的:)这种方法似乎不起作用。最终,函数返回SQL,但它会像通常的字符串一样被括在括号中。甚至Hibernate也将其类型显示为VARCHAR。有没有办法将函数呈现为SQL而不是字符串?您指的是哪种括号?字符串通常用单引号(”
)括起来,而不是用括号括起来。我自己实现了不止一个SQLFunction
,并且确信Hibernate通常不会添加引号或括号。
dialect.registerFunction("myOrderFunction", new MyOrderFunction());
@Formula("my huge SQL")
private String orderAttribute;
... ORDER BY entity.orderAttribute ASC
query.orderBy(criteriaBuilder.asc(root.get(ExampleEntity_.orderAttribute))));