【问题标题】:Hibernate returns list with null values (OneToMany annotation with List type)Hibernate 返回具有空值的列表(具有 List 类型的 OneToMany 注释)
【发布时间】:2012-10-29 18:13:58
【问题描述】:

我遇到了一个问题,Hibernate (4.1.8.FINAL) 返回一个包含 NULL 值的列表(单向 OneToMany 映射)。

我得到了什么: 我得到一个大小为 21 的列表,其中 EntryAddress 在第 10 个索引上,第二个条目地址在第 20 个索引上。

Entry [addresses=[null, null, null, null, null, null, null, null, null, null, EntryAddress [id=5, entryId=3, precedence=10, line=Line 3.1], null, null, null, null, null, null, null, null, null, EntryAddress [id=6, entryId=3, precedence=20, line=Line 3.2]]]

我的期望 - 我期望一个只有两个 EntryAddress 对象的列表:

Entry [addresses=[EntryAddress [id=5, entryId=3, precedence=10, line=Line 3.1], EntryAddress [id=6, entryId=3, precedence=20, line=Line 3.2]]]

这是最小的源代码:

@Entity
@Table(name = "entry")
public class Entry {
    ...
    @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "entry_id")
    @OrderColumn(name = "precedence")
    private List<EntryAddress> addresses;
    ...
}
@Entity
@Table(name = "entry_address")
public class EntryAddress {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;

    @Column(name = "entry_id")
    private Integer entryId;

    @Column(name = "precedence")
    private Integer precedence;
...
}

这是mysql结构(引擎InnoDB):

CREATE TABLE  entry  (
   id  int(10) unsigned NOT NULL AUTO_INCREMENT,
   name  varchar(500) NOT NULL,
   active  int(1) NOT NULL DEFAULT '0',
   modifiedTS  timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
   createdTS  timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY ( id )
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

CREATE TABLE  entry_address  (
   id  int(10) unsigned NOT NULL AUTO_INCREMENT,
   entry_id  int(10) unsigned NULL,
   precedence  int(2) NULL DEFAULT '0',
   line  varchar(255) DEFAULT NULL,
  PRIMARY KEY ( id ),
  UNIQUE KEY  entry_address_uq  ( entry_id , precedence )
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

当我尝试用“Set”替换“List”时,集合没有 NULL 值,但顺序/优先级不起作用。

我发现的一个有趣的点是,如果我将第一个 EntryAddress 的优先级设置为 1,并将第二个 EntryAddress 的优先级设置为 2,那么我将得到一个大小为 2 的列表。所以似乎优先级在返回过程中起作用的列表虽然优先级应该只用于排序。

你能告诉我我做错了什么吗?谢谢你:-)

【问题讨论】:

    标签: java mysql hibernate


    【解决方案1】:

    我找到了解决方案,我使用它,这解决了问题

    @OneToMany(orphanRemoval = true)
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "entry_id")
    @OrderBy("precedence")
    private List<EntryAddress> addresses;
    
    @OneToMany(orphanRemoval = true)
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "entry_id")
    @OrderBy("precedence")
    private List<EntryContact> contacts;
    

    【讨论】:

    • 请扩展您的答案。它的哪一部分解决了您的问题? @LazyCollection ?
    【解决方案2】:

    来自 OrderColumn 的 javadocs: "订单列必须是整数类型。持久化提供程序在更新关联或元素集合时维护订单列值的连续(非稀疏)排序。第一个元素是 0。”

    因此,期望 OrderColumn 的值从 0 开始并且是连续值。因此,当值不连续时,Hibernate 会将空元素添加到您的 Java 列表中。

    我认为 OrderColumn 的这种行为类似于 hibernate xml 映射中的列表索引行为。

    【讨论】:

      【解决方案3】:

      问题在于List和Set的区别。

      我得到一个大小为 21 的列表,其中 EntryAddress 在第 10 个索引上,第二个 Entry Address 在第 20 个索引上。

      这简直就是一个应该是 List 的 Set!

      当您“用 Set 替换 List”时,您是否记得删除了 @OrderColumn(name = "precedence")?因为如果您使用 Set,则不能有 Order 列。

      【讨论】:

      • 感谢您的回复。是的,我知道如果必须使用 Set,我必须删除 @OrderColumn,但我还想按优先列对 EntityAddress 进行排序。这就是我尝试使用 List 类型的原因。建议:-) ?我也尝试了 OrderBy 注释,但在那里失败了。
      猜你喜欢
      • 2020-09-23
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      • 2012-10-26
      • 2021-08-03
      • 2018-05-26
      • 2018-01-11
      • 1970-01-01
      相关资源
      最近更新 更多