我遇到的问题是Hibernate(4.1.8.FINAL)返回一个包含NULL值的列表(单向OneToMany映射)。
我得到了什么: 我得到一个大小为21的List,其中EntryAddress在第10个索引上,第二个Entry Address在第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]]]
我的期望 - 我希望List只有两个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;
当我尝试将“List”替换为“Set”时,集合没有NULL值,但序列/优先级不起作用。
我发现一个有趣的观点是,如果我将1st EntryAddress的优先级设置为1,并将2nd EntryAddress的优先级设置为2,那么我将得到一个大小为2的List。因此看起来优先级在返回时起作用虽然优先级只应用于排序。
你能告诉我我做错了什么吗?谢谢: - )答案 0 :(得分:14)
来自OrderColumn的javadoc: “订单列必须是整数类型。持久性提供程序在更新关联或元素集合时维护订单列值的连续(非稀疏)排序。订单列值为第一个元素是0。“
因此,期望OrderColumn的值从0开始并且是连续值。因此,当值不连续时,Hibernate会将空元素添加到Java列表中。
我认为OrderColumn的这种行为类似于hibernate xml映射中的list-index行为。
答案 1 :(得分:2)
问题是List和Set之间的区别。
我得到一个大小为21的List,其中EntryAddress在第10个索引上,第二个Entry Address在第20个索引上。
这是一个非常好的集合,它应该是List!
当您“将List替换为Set”时,您是否记得删除@OrderColumn(name = "precedence")
?因为如果您使用Set,则不能有Order列。
答案 2 :(得分: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;