我是使用 EclipseLink 的 JPA 命名查询的新手,我想“忽略”命名查询中具有空值的属性。我知道我的问题已经被回答过很多次了。 例如JPA 查询处理 NULL 参数值
但是,在我的情况下,以下格式不起作用
+ " AND (:quoteNumber IS NULL OR ord.quoteNumber = :quoteNumber)"
我收到错误“非法使用关键字空”。我现在将使用 CriteriaQuery,只是好奇为什么它在命名查询中不起作用。 以下是正在使用的 DB2 和 Eclipselink 版本。 eclipse链接:2.5.1 DB2:DSN11015
JPA 规范这么说
3.8.13 命名查询
命名查询是用元数据表示的静态查询。命名查询可以用 Java 持久性查询语言或 SQL 来定义。查询名称的范围仅限于持久性单元。
所以你不能真正期望它们在运行时基于某些空条件而改变。正如您所指出的,标准查询本质上是动态的,因此这将是可行的方法。
根据评论进行编辑:
AND (ord.quoteNumber = :quoteNumber or :quoteNumber is null or :quoteNumber = ''
不更改运行时的查询(不跳过子句)。它将该子句评估为 TRUE。 DB2(以及据我所知的 Derby)的问题是,它们不允许按照 API PreparedStatement.setObject“将非类型化 Null 发送到后端”。您可以通过强制转换设置类型来测试它
AND (ord.quoteNumber = cast(:dfdTxt as integer) or cast(:dfdTxt as integer) is null or cast(:dfdTxt as integer) = ''
因此,这种方法是特定于数据库实现的,并且可能会在某些时候发生变化。
持久性.xml:
<properties>
<property name="eclipselink.ddl-generation" value="none" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1;MODE=Oracle;DEFAULT_NULL_ORDERING=HIGH"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.jdbcx.JdbcDataSource"/>
<property name="eclipselink.logging.level" value="SEVERE" />
<property name="eclipselink.logging.parameters" value="false" />
<property name="eclipselink.target-database" value="Oracle"/>
</properties>
NamedQuery 失败:
NamedQuery(
name = "myquery",
query = " select count(job.id), 'job' as tabelle" +
" from Job job"
" UNION" +
" select count(xyz.id), 'xyz' as tabelle" +
" from Xyz xyz"
)
结果:
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.14.v20231208-d05cebc9b0): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLNonTransientException: Unbekannter Datentyp: "?, ?"
Unknown data type: "?, ?"; SQL statement:
(SELECT COUNT(t0.ID), ? FROM JOB t0) [50004-224]
Error Code: 50004
可以通过在 SQL Select 语句中使用
cast()
来修复此错误:
@NamedQuery(
name = "myquery",
query = " select count(job.id), cast('job' as VARCHAR2(30)) as tabelle" +
" from Job job"
" UNION" +
" select count(xyz.id), cast('xyz' as VARCHAR2(30)) as tabelle" +
" from Xyz xyz"
)