我正在使用JPQL查询来访问Oracle数据库函数:select FUNCTION('function_name', 'foo', 1234) from com_mycompany_bar obj
这个查询可以正常工作,函数也被调用了。但事实上,我并不需要FROM
子句,我更愿意将其留空,而不是为了符合语法规范而访问实体。
在这种情况下,我有什么最佳选择?
我看到有几个可能的答案:
在标准JPA中,有两个选项,都涉及Oracle的DUAL
“表”:
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");
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
:
Eclipselink:
Hibernate:
JPQL语法要求存在FROM子句(例如,请参见此处或此处)。
通过本地查询通常调用存储过程/函数(请参见:createNativeQuery)。 因此,这应该可以工作:
em.createNativeQuery("select function_name('foo', 1234)").getSingleResult()
更新(来自评论):
确实JPA本地查询不支持命名参数。因此,您必须决定哪个对您来说更少的罪恶:要么使用带有不必要实体引用的JPQL,要么使用位置参数而不是命名参数的本地查询。
但请注意,FUNCTION是EclipseLink扩展,因此如果您决定更改供应商,则无法使用它。
(Session)em.getDelegate()
(如果你在底层使用Hibernate),并从Hibernate中调用支持命名参数的本地查询(参见:https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html#d0e13930)。但那似乎更糟糕。 - Piotr Sobczyk
From
子句吗?select FUNCTION('function_name', 'foo', 1234)
? - Siyual