oracle 带有ODER BY CASE表达式的条件API抛出SQLException:ORA-12704“字符集不匹配”

yhxst69z  于 2023-03-01  发布在  Oracle
关注(0)|答案(1)|浏览(171)

我正在使用条件API来创建我的查询。由于特殊的排序算法,我使用了一个“按大小写排序”表达式。我的单元测试在内存中使用了H2 DB,并且正在工作。在开发阶段,我们使用Oracle DB,并且在那里我得到了一个“SQLException:“ORA-12704”。
假设我的根实体'Foo'有一个'Bar'的集合。Bar有一个属性'myOrderByColumn'

public class Bar {
    ...

    @NotBlank
    @javax.validation.constraints.Size(max = 255)
    @Column(name = "MYORDERBYCOL")
    private java.lang.String myOrderByColumn;

    ...
}

下面是产生异常的代码,它创建稍后在CriteriaQuery中使用的Order对象。orderBy(..)

private Order buildOrderBy(final CriteriaBuilder cb,
         final Root<Foo> rootEntity, 
         final List<String> somehowSpecialOrderedList) {
            
      final Expression<String> orderByColumn =
            rootEntity.join(Foo_.bars, JoinType.LEFT).get(Bars.myOrderByColumn);

      CriteriaBuilder.SimpleCase<String, Integer> caseRoot = cb.selectCase(orderByColumn);

      IntStream.range(0, somehowSpecialOrderedList.size())
            .forEach(i -> caseRoot.when(somehowSpecialOrderedList.get(i), i));

      final Expression<Integer> selectCase = caseRoot.otherwise(Integer.MAX_VALUE);

      return cb.asc(selectCase);
   }

我查看了Oracle数据库,列“myOrderByColumn”的类型是NVARCHAR 2(255)。
我猜这里的问题是SQL查询中的“when”部分必须与数据库列“MYORDERBYCOL”的类型匹配,即NVARCHAR 2。在Java中我使用字符串。可能Hibernate没有正确地转换此类型!?
我可以通过以下方式生成数据库ORA-12704错误

SELECT FOO.id
FROM FOO
LEFT OUTER JOIN BAR ON FOO.id = BAR.fk_id
ORDER BY
   CASE FOO.myorderbycol
      WHEN '20' THEN 1
      ELSE           2
   END ASC;

此SQL有效

SELECT FOO.id
FROM FOO
LEFT OUTER JOIN BAR ON FOO.id = BAR.fk_id
ORDER BY
   CASE FOO.myorderbycol
      WHEN cast('20' as NVARCHAR2(255)) 
      THEN 1ELSE           2
   END ASC;

我必须如何使用标准API调整我的按情况排序表达式,以便查询适用于任何数据库?(以后必须至少适用于H2、Oracle、MS SQL、PostgreSQL)

pkwftd7m

pkwftd7m1#

在我看来是Oracle的问题。您使用的是哪个版本?您可以尝试其他可能有效的方法。

CriteriaBuilder.SearchedCase<Integer> caseRoot = cb.selectCase();

  IntStream.range(0, somehowSpecialOrderedList.size())
        .forEach(i -> caseRoot.when(cb.equal(orderByColumn, somehowSpecialOrderedList.get(i)), i));

  final Expression<Integer> selectCase = caseRoot.otherwise(Integer.MAX_VALUE);

相关问题