Hibernate将NULL值放入列表中。

12

我继承了一段使用Hibernate的Java代码。现在有些人使用此代码时报告他们到处都遇到了NullPointerExceptions。

我已经找到问题所在,发现当我们执行从数据库中提取对象列表的查询时,其中一个表格中的对象列表(从另一个表格中提取)似乎会留下空洞(NULL值)。因此,该列表可能看起来像:

Object
Object
NULL
Object

我们正在使用的代码从数据库中提取信息:

List<PrinterGroup> groups = 
    this.getSession().createQuery( "from PrinterGroup" ).list();

每个打印机组内部都有一个包含 NULL 值的过滤器列表。

虽然我可以四处寻找我们循环遍历此列表并添加 NULL 检查的每个实例,但我觉得这只是一个权宜之计,必须有一种方法告诉 Hibernate 不要获取 null 值。

编辑:

  • 我们正在使用 Hibernate 3.2.2

编辑2:

所以数据库似乎很困惑。 PrinterGroup->Filter 关系是一对多关系。 因此,PrinterGroups 拥有一个过滤器列表。 问题在于当列表出现时,其中的过滤器列表具有 null 值(顺便说一下,数据库中没有 null 值),而列表看起来像上面那样。

编辑3:

以下是 PrinterGroup HBM 中相关映射部分。

<subclass name="PrinterGroup" discriminator-value="PG">
   <list name="filters"
              lazy="true"
              table="PG_FILTER"
               inverse="false"
                cascade="all-delete-orphan">

        <key>
           <column name="PG_ID" not-null="false"/>
        </key>
        <index column="LISTPOSITION"/>
        <one-to-many class="Filter"/>
     </list>

过滤器是一个相当基本的POJO映射。


你是否正在使用<list><list-index>来映射集合?请发布你的.hbm映射文件。 - matt b
我发布了PrinterGroup HBM的一部分,其中包括过滤器映射。 - Patrick McDaniel
5个回答

19

这个集合是否与 <list>(或其他索引集合)和 <list-index> 配对映射?

所有集合映射,除了具有set和bag语义的映射,都需要在集合表中有一个索引列。 索引列是映射到数组索引、List索引或Map键的列。...数组或列表的索引始终是整数类型,并且使用 元素进行映射。 映射的列包含默认从零开始编号的连续整数。

我想象当使用索引集合时,如果您的索引列中有间隙(即它有像 0, 1, 3, 7 这样的值),Hibernate将在预期位置填充结果的空元素。


这是正确的。如果您的编号序列中有间隔,返回的列表中将会出现 null 值。 - Cowan
这正是正在发生的事情。现在需要找出如何在已经激活的系统上进行纠正。 - Patrick McDaniel
更改数据库值,使LISTPOSITION值连续? - matt b
更多信息请参见http://www.coderanch.com/t/217438/ORM/java/Hibernate-returning-List-NULL-values(Stefan Zauner的帖子) - Kimble
启发性的答案。谢谢。 据我所知,此解决方案只在索引之间的空缺处“保存”null值。但是列表末尾的null值怎么办?有没有办法也将它们保存下来? 例如:[null,null,1,2,null,null] - miguelcobain
1
未来的谷歌员工请注意(如果你正在使用 hibernate 以外的方式向数据库插入数据),hibernate 总是假定 BASE-0,而不是 BASE-1。因此,如果您将索引输入为 1、2、3、4、5,则 hibernate 将在每个列表开头插入一个 NULL。索引值从 0 开始——所以应该输入 0、1、2、3、4。 - Paul

2
List<PrinterGroup> groups = this.getSession().createCriteria( PrinterGroup.class ).add(Restrictions.isNotNull("filters")).list();

1

好的,那么PrinterGroup对象本身并不为null,但它们对于Filter类型的对象具有null引用?或者是对于包含null Filters的Filters列表具有非null引用?

显而易见的答案是数据库在PrinterGroup和Filter之间包含多对多关系,并且对于filters存在数据库null值,例如:

 select * from printer_group_filter;
 id    printergroup_id   filter_id
 1     1                1
 2     1                null
 3     1                2
 4     2                1
 5     2                null

如果过滤器可能为空,那么这是您的要求。或者您可以使用NullObject惯用语将“空过滤器”变成实际对象,但是在Hibernate中这并不直接。
如果过滤器不可能为空,请修复数据,向多对多添加非空约束,并修复输入验证以防止添加更多的null。

我已经编辑了我的帖子。PrinterGroup和Filter表之间存在一对多的关系。因此,PrintersGroups可能有许多过滤器。当我们在Java中获取它们的列表时,Filters列表中会有空值。 - Patrick McDaniel

0
如何只使用HQL来过滤掉空过滤器呢?
List<PrinterGroup> groups = 
    this.getSession().createQuery( "Select pg from PrinterGroup pg where pg.filter is not null" ).list();

我假设你的属性叫做“filter”


0
你应该对空值进行检查,或者重新排序列表以摆脱空值。这很麻烦。

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