虽然执行的SQL语句返回了值,但Hibernate返回了一个空列表

12

我正在使用Hibernate作为ORM映射器。我想执行一个实际上相当简单的HQL查询:

SELECT a 
FROM Foo a 
WHERE a.status = :A0status 
ORDER BY a.bookingTypeCode ASC, 
         a.priority ASC

这个HQL查询会被转换成一个SQL查询,看起来大概是这样的:

select a.* 
from Foo a 
where a.status='A' 
order by a.bookingtypecode ASC, 
         a.priority ASC

我在Oracle SQL Developer上执行SQL查询时,返回17行结果。然而,当我使用Querylist方法执行hql查询时,得到的是一个由17个null元素组成的列表。虽然元素数量正确,但实际上没有一个元素被加载。

以下是我创建和执行查询的方式:

// the hql query is stored in the hqlQuery variable;
// the parameter are stored in a Map<String, Object> called params
Query hQuery = hibSession.createQuery(hqlQuery);
for (Entry<String, Object> param : params.entrySet()) {
    String key = param.getKey();
    Object value = param.getValue();
    hQuery.setParameter(key, value);
}

List<?> result = hQuery.list();

执行query.list()后我得到的结果。

有人知道这里可能存在什么问题吗?

更新1

我最近从hibernate 3.2升级到4.3.5。在升级之前一切都运行良好。升级之后我遇到了这个错误。


请问您能否发布实体Foo类的代码? - Zeus
你是否正在查询一个视图?必须有一个唯一的索引列,Hibernate 才能用它来映射回 Foo 实体的 id 属性。 - skarist
@Zeus 我认为这并没有帮助,因为我们不使用标准的Hibernate实体。它是自制的(几年前),在这里解释起来相当复杂。尽管如此,这不应该是问题所在。原因在于更新后的问题。谢谢。 - mvieghofer
@skarist 是的,它可以是一个视图。谢谢你的提示,我会去查看一下。 - mvieghofer
@skarist 不,我是从一个表中进行选择... - mvieghofer
如果数据库中任何一个主键列(@Id)的值为null,则该记录的整个Hibernate对象将为null。 - firstpostcommenter
4个回答

20

我已将Hibernate的日志级别设置为TRACE并发现了问题。实际上,这是一个映射/逻辑/数据库错误。根据实体类,主键由两个列组成,其中一个列是可为空的。然而,主键永远不能为可空。因此,Hibernate总是返回null。


对我有用,我已经在我的域类中切换了需要使用@Id注释的列,这是Hibernate将DB对象映射到其中的。在我的情况下,我的表没有主键,但是注释仍然导致空值,因为Hibernate不希望在从DB查询结果创建的实例中有空ID,无论它是否是主键。 - Jeremy
我必须将日志级别设置为“FINEST”,这在我的情况下是一个查询问题。对于想知道如何设置日志级别的任何人,请参见https://dev59.com/YnRA5IYBdhLWcg3wvQhh#847121。 - banan3'14

3
如果您没有设置自定义(并存在错误)的ResultTransformer,我的第二个猜测是您的调试器在骗你。您的代码是否实际接收到一个空列表?此外,请确保使用您展示的代码进行测试。太多时候,人们会简化事情,而魔鬼却隐藏在细节中。

嗨,我没有设置自定义的ResultTransformer,返回的列表实际上是一个空列表(因此我会因此得到NullPointerException)。另外,我上面发布的SQL基本上就是Hibernate生成的SQL(我只是通过选择*和更改别名来简化它)。 - mvieghofer

1

我遇到了这个错误。MySQL查询浏览器可以工作,但在7列的Hibernate中,只有一个列始终带有所有空字段。我检查了所有的ID,它们都不是空的。错误出现在SQL Native的构建中。我不得不改变写法。最终解决了问题。

SELECT c.idContratoEmprestimo as idContratoEmprestimo,
c.dtOperacao as dataOperacao,
p.cpf as cpf,
p.nome as nome,
(Select count(p2.idParcelaEmprestimo) from EMP_PARCELA p2 where p2.valorPago > 0 and p2.dtPagamento is not null
and p2.idContratoEmprestimo = c.idContratoEmprestimo and p2.mesCompetencia <= '2014-08-01') as parcelasPagas, c.numeroParcelas as numeroParcelas,
pe.valorPago as valorParcela
FROM EMP_CONTRATO c inner join TB_PARTICIPANTE_DADOS_PLANO AS pp on pp.idParticipantePlano = c.idParticipantePlano
inner join TB_PARTICIPANTE as p on p.id = pp.idParticipante
inner join TB_PARTICIPANTE_INSTITUIDOR as pi on pi.PARTICIPANTE_ID = p.id
inner join EMP_PARCELA as pe on pe.idContratoEmprestimo = c.idContratoEmprestimo
where c.dtInicioContrato <= '2014-08-01' and pi.INSTITUIDOR_ID = 1
and c.avaliado is true
and pe.mesCompetencia = '2014-08-01'
and c.deferido is true
and c.dtQuitacao is null
and c.dtExclusao is null
and pe.valorPago is not null
group by c.idContratoEmprestimo
order by p.nome

0
在将遗留代码升级到Hibernate 5并修复单元测试的过程中,我遇到了这个错误。主键(在我的情况下是复合键)由两列组成(根据实体类)。然而,测试数据没有为这两列填充数据。在较新版本的Hibernate中,主键(或复合键的一部分,在我的情况下)永远不能为null。因此,Hibernate始终返回null。
我只需更新测试数据,包括形成复合键的两列的数据,Hibernate就开始返回有效结果了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接