3

[编辑:显然,这只是数组的问题,FoxyBOA 的答案可能指向(甚至是)答案。]

我的问题与这些软件有关:Hibernate3+Annotation、Spring MVC、MySQL,在这个例子中还有 Spring Security。

我想知道,为什么由 Hibernate 自动关联的集合包含子表的每个行号的空值(除了正确的元素)。我的例子:

我有一个用户和一个权限表,用户表的主键是用户名作为外键。现在,我的权限表中有 13 行。当我从数据库(MySQL InnoDB)中检索用户时,Hibernate 会自动检索与此映射对应的用户权限:

@OneToMany
@JoinColumn(name = "username")
@IndexColumn(name="id") // "id" was the primary key and is used to sort the elements
public Authority[] getAuthorities() {
    return authorities;
}
public void setAuthorities(Authority[] authorities) {
    this.authorities = authorities;
}

...我最终得到一个包含 14 (0-13) 个元素的集合“权限”,其中只有四个不为空(数据库表中的四行属于该特定用户,所以这是正确的)。据我所知,我正在为 Fetchmode 等属性使用 Hibernate 默认值。我得到的用户是这样的:

Criteria criteria = getSession().createCriteria(User.class);
criteria.add(Restrictions.eq("username",username));
User user = (User) criteria.uniqueResult();

来自 org.hibernate.loader.loader 的日志信息正确地“提及”了结果集的四行。尽管如此,用户创建的数组中有四个正确的元素加上十个空值。在我的具体示例中,这会导致此异常:

java.lang.IllegalArgumentException: Granted authority element 0 is null - GrantedAuthority[] cannot contain any null elements
4

2 回答 2

3

答案在于@IndexColumn 注释。它使用 id 的值作为数组索引,因此 Array 中的元素个数基本上是 Authorities 表中 ID 最高的值。

请参阅有关索引集合的休眠文档

尝试删除注释。

也只是一个念头;您是否考虑过使用 Set 进行映射?这不是绝对必要的,它只是一种更常见的映射形式。

于 2009-05-26T19:01:24.567 回答
2

我可以建议你检查你的数据。如果您有丢失的索引(在您的情况下为 id 列),那么您将在数组中获得 null 而不是丢失的 id 。IE

table authorities:
username id
bob 1
bob 3
bob 5

结果,您将拥有一个数组: {0=null, 1=bob, 2=null, 3=bob, 4=null, 5=bob}

更新: 我在两种情况下遇到了这种情况:

  1. 权限表的索引列id中缺少键值(例如 0,1,3,4,5 - 缺少值 2。Hibernate 将自动添加到键为 2 且值为 null 的数组值)。
  2. 索引值是按顺序排列的,但选择标准过滤其中的一部分(例如,您的 HQL 类似于“从用户 u 加入 u.authorities a where a.id=2”。在这种情况下,休眠加载用户,但在权限数组中你将只有 3 个值:0 - null、1 - null、2 - id 为 2 的权限。
于 2009-05-26T17:08:25.670 回答