您不能在 JPQL 或条件查询中使用 SQL 片段...
... 除非...
1。调用函数
JPA 和 Hibernate 允许在其表达式中使用函数,例如:
... ORDER BY trim(entity.label) ASC
回复
query.orderBy(criteriaBuilder.asc(
criteriaBuilder.function("trim", String.class, root.get(ExampleEntity_.label))));
问题是,这实际上并不是对 SQL 函数 trim 的调用,而是对 JPA 函数的调用,它必须被注册(Hibernate 已经为最常见的 SQL 函数这样做了)。
幸运的是,您可以在 DialectResolver 中定义自己的 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 的 SQL 服务器中创建自己的函数并将其注册为函数:
dialect.registerFunction("myOrderFunction",
new StandardSQLFunction("myOrderFunctionInSQL", StringType.INSTANCE));
或者您可以编写自己的映射,其中包括您的庞大的 SQL:
public class MyOrderFunction implements SQLFunction {
public String render((Type firstArgumentType, List arguments,
SessionFactoryImplementor factory) throws QueryException) {
return my_huge_SQL;
}
// ...
}
然后注册那个:
dialect.registerFunction("myOrderFunction", new MyOrderFunction());
此解决方案的另一个优点:您可以根据实际的数据库方言定义不同的 SQL。
2。使用公式
您可以为您的实体使用附加属性:
@Formula("my huge SQL")
private String orderAttribute;
您现在可以按此属性排序:
... ORDER BY entity.orderAttribute ASC
回复
query.orderBy(criteriaBuilder.asc(root.get(ExampleEntity_.orderAttribute))));
我只推荐这个解决方案,如果您仍然需要模型中巨大的 SQL 的结果。否则它只会污染您的实体模型并将 SQL 添加到您的实体的每个查询中(除非您用@Basic(fetch = FetchType.lazy) 标记它并使用字节码检测)。 p>
类似的解决方案是使用庞大的 SQL 定义 @Subselect 实体 - 具有相同的缺点。