在JPQL中空白的FROM子句是什么意思?

5

我正在使用JPQL查询来访问Oracle数据库函数:select FUNCTION('function_name', 'foo', 1234) from com_mycompany_bar obj

这个查询可以正常工作,函数也被调用了。但事实上,我并不需要FROM子句,我更愿意将其留空,而不是为了符合语法规范而访问实体。

在这种情况下,我有什么最佳选择?


1
我不熟悉JPQL,但你不能完全省略From子句吗? select FUNCTION('function_name', 'foo', 1234) - Siyual
@Siyual 不错的想法,但不幸的是JPQL需要一个FROM子句。 - Roland
2个回答

10

我看到有几个可能的答案:

在标准JPA中,有两个选项,都涉及Oracle的DUAL“表”:

  1. DUAL 映射到实体并在 FROM 子句中使用它。 它是更“JPQL”的方法,但需要更多操作:

在Java代码中:

@Entity(name = "Dual")
@Table(name = "SYS.DUAL")
public class Dual {
    @Id
    @Column(name = "DUMMY")
    private String dummy;
}

在 orm.xml 中:

<named-query name="yourQuery">
    <query><![CDATA[
        SELECT FUNCTION('function_name', 'foo', 1234) FROM Dual d
    ]]>
    </query>
</named-query>

在客户端代码中:

Query q = entityManager.createNamedQuery("yourQuery");
  1. 只需使用一个使用 DUAL 的本地查询。

在 orm.xml 中:

<named-native-query name="yourQuery">
    <query><![CDATA[
        SELECT function_name('foo', 1234) from sys.dual
    ]]>
    </query>
</named-native-query>

在客户端代码中:

Query q = entityManager.createNativeQuery("yourQuery");

作为最后一种选择,您可以使用一些 JPA 实现扩展来避免使用 DUAL


非常感谢,这是一个很棒的解决方案。 - Sir. Hedgehog

1
简而言之:我认为无法跳过JPQL查询的FROM子句

JPQL语法要求存在FROM子句(例如,请参见此处此处)。

通过本地查询通常调用存储过程/函数(请参见:createNativeQuery)。 因此,这应该可以工作:

em.createNativeQuery("select function_name('foo', 1234)").getSingleResult()

更新(来自评论):

确实JPA本地查询不支持命名参数。因此,您必须决定哪个对您来说更少的罪恶:要么使用带有不必要实体引用的JPQL,要么使用位置参数而不是命名参数的本地查询。

但请注意,FUNCTION是EclipseLink扩展,因此如果您决定更改供应商,则无法使用它。


我知道可以使用本地查询来实现。StoredProcedureQuery仅适用于存储过程,而不适用于函数 - Roland
@Roland,那你为什么不能使用本地查询而必须使用JPQL查询呢?看起来你选错了工具来完成这项工作。 - Piotr Sobczyk
本地查询不支持命名参数,只支持位置参数。 - Roland
哦,我明白了。在我看来,你必须选择两害相权取其轻:要么使用带有不必要实体引用的JPQL,要么使用位置参数而不是命名参数的本地查询。附言:第三个选项是使用 (Session)em.getDelegate()(如果你在底层使用Hibernate),并从Hibernate中调用支持命名参数的本地查询(参见:https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html#d0e13930)。但那似乎更糟糕。 - Piotr Sobczyk
没错。将DUAL映射为实体(请参见其他答案)也是可能的,但这看起来有些过度设计了。 - Roland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接