我在我的 Java 项目中使用 Hibernate v3.6.4。当我尝试在 HQL 查询中使用命名参数的参数列表时遇到问题。
基本上,我想获取与
IN
子句中提到的 ID 之一匹配的所有记录。
我尝试同时使用 HQL 和 Criteria,但得到了相同的结果。
我的HQL查询:
Set<String> reportIds = new HashSet<String>();
reportIds.add("1");
reportIds.add("2");
String whereClause = "from Report where id IN (:reportIds) ";
Query query = session.createQuery(whereClause);
query.setParameterList("reportIds", reportIds);
输出 = 空列表。虽然我通过在终端中手动执行sql查询来检查确实有这样的记录。
我打开了日志记录,这是我看到的:
休眠:
/*
from
Report
where
id IN (
:ids
) */ select
mediavalue0_.id as id31_,
...
from
report mediavalue0_
where
mediavalue0_.id in (
?
)
HibernateLog --> 13:22:36 TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - 1,2
这是非常不正常的,因为如果你注意到最后的bind语句,它会考虑
toString()
的Set
,即"1,2"
而不是"1"
然后"2"
!
我正在搞乱它,所以一时兴起,我决定直接在
Set
方法调用本身中创建 setParameterList()
的实例。就像这样,
query.setParameterList("reportIds", Sets.newHashSet("1","2"));
它成功了!顺便说一句,
Sets.newHashSet()
是 Google 的 Guava 库提供的构造。我使用相同的库来生成原始的 reportIds
集。所以,那里没有不一致的地方。
此查询转换为以下 TRACE:
from
Report
where
id IN (
:ids
) */ select
mediavalue0_.id as id31_,
...
from
report mediavalue0_
where
mediavalue0_.id in (
? , ?
)
HibernateLog --> 13:28:57 TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - 1
HibernateLog --> 13:28:57 TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [VARCHAR] - 2
注意
VARCHAR
的单独绑定。
我对这种奇怪的行为感到非常困惑。也许你们中的一些人可以指出我做错了什么。
仅供参考,我使用的标准构造(&导致了相同的输出),就像:
Criteria criteria = session.createCriteria(Report.class);
criteria.add(Restrictions.in("id", reportIds));
附注我还使用了具有相同结果的命名 SQL 查询:
<sql-query name="reportByIds">
<return class="report.Report"/>
SELECT mvr.* from report mvr
WHERE mvr.id IN :ids
</sql-query>
更新:
我发现了问题。有点尴尬。客户端代码发送 1 个元素的
Set
,这是报告 ID 的串联 String
。啊啊!
假设 id 属性的类型为
Long
Set<Long> reportIds = new HashSet<Long>();
reportIds.add(1l);
reportIds.add(2l);
那么查询应该可以工作,条件也可以工作