我有一个具有CLOB属性的实体:
public class EntityS {
...
@Lob
private String description;
}
为了从数据库中检索特定的EntityS,我们使用CriteriaQuery,我们需要结果是唯一的,所以我们这样做:
query.where(builder.and(predicates.toArray(new Predicate[predicates.size()]))).distinct(true).orderBy(builder.asc(root.<Long> get(EntityS_.id)));
如果我们这样做,我们会得到以下错误:
ORA-00932: inconsistent datatypes: expected - got CLOB
我知道这是因为在选择CLOB时不能使用distinct。但我们需要CLOB。使用带谓词的CriteriaQuery等是否有解决方法?
我们使用了一个丑陋的解决方法,去掉.unique(true),然后过滤结果,但这是垃圾。我们使用它只是为了能够继续开发应用程序,但我们需要一个更好的解决方案,而我似乎找不到。。。
如果您使用Hibernate作为持久性提供程序,您可以指定以下查询提示:
query.setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false);
这样,"distinct"就不会传递给SQL命令,但Hibernate将只负责返回不同的值。
有关详细信息,请参阅此处:https://thoughts-on-java.org/hibernate-tips-apply-distinct-to-jpql-but-not-sql-query/
跳出框框思考-我不知道这是否可行,但也许值得一试。(我测试了它,它似乎可以工作,但我创建了一个只有一列、CLOB数据类型和两行的表,这两行的值都为to_clob('abcd')
——当然,它应该在设置上工作。)
要消除重复,请计算每个clob的哈希,并指示Oracle计算一个按哈希值划分并按零排序的行号(null)。然后只选择行号为1的行。如下所示(t
是我创建的表,其中一个CLOB列称为c
)。
我预计执行时间应该相当不错。当然,最大的担忧是碰撞。不错过任何CLOB有多重要?首先,基表中有多少行?类似"十亿分之一的几率"的碰撞可以接受吗?
select c
from (
select c, row_number() over (partition by dbms_crypto.hash(c, 3) order by null) as rn
from t
)
where rn = 1;
注意-用户(在您的情况下是您的应用程序)必须对SYS.DBMS_CRYPTO
具有EXECUTE
权限。如果需要,DBA可以授予它。