0

我在 Eclipselink 中有一个复杂的动态查询,它的 case 表达式涉及两个不同的列,一个是 VARCHAR2,一个是 NVARCHAR2。

它需要是一个 case 表达式,因为我还希望能够按该结果列进行排序,所以我不能同时查询两者。在 Java 中,两者都只是映射为一个字符串,所以你甚至看不出有什么区别。

对于我的查询,Eclipselink 创建了以下选择表达式:

CASE
  WHEN (t9.STRINGVALUE IS NOT NULL)
  THEN t9.STRINGVALUE
  ELSE t10.OTHERSTRINGVALUE
END ,

标准代码为:

Expression<String> str = firstRoot.get("stringValue");
Expression<String> strExp = cb.<String> selectCase().when(cb.isNotNull(str), str)
.otherwise(otherRoot.<String> get("otherStringValue"));
q.multiselect(..., strExp, ...);

这会导致 Oracle 失败并出现 ORA-12704:字符集不匹配。我想修改代码以产生

cast(t10.OTHERSTRINGVALUE as NVARCHAR2(50),

但我不知道怎么做。

我在实体字段上尝试了一个转换器,或者在两个字段的 .get() 表达式上尝试了一个 .as(String.class)。

所以问题是:有没有办法将像 NVARCHAR2 这样的 Oracle 类型传递给 .as() 表达式?我是否可以使用标准 API 插入对 CAST(... as NVARCHAR2) 的调用?有没有其他方法可以让它生成自定义 SQL,因为我真的无法重写整个查询,只是因为 JPA 或 EL 不提供您可能需要一些自定义 SQL 的可能性......

4

1 回答 1

0

在标准 API 中执行此操作的唯一方法是从 otherRoot 创建一个新的 PathImpl。get("otherStringValue") 路径,传入一个 EclipseLink 原生转换表达式作为表达式节点。就像是:

PathImpl path = (PathImpl)otherRoot.<String> get("otherStringValue");
Path castPath = new PathImpl(path, em.getMetamodel(), path.getJavaType(), path.getCurrentNode().cast("NVARCHAR2"), path.getModel());

Expression<String> str = firstRoot.get("stringValue");
Expression<String> strExp = cb.<String> selectCase().when(cb.isNotNull(str), str)
.otherwise(castPath );
q.multiselect(..., strExp, ...);
于 2013-07-30T14:57:02.137 回答