Wolfram
Wolfram

Reputation: 8052

Why do associated collections contain null values? (Hibernate, Annotation, Spring)

[Edit: Apparently, this is only an issue for arrays and FoxyBOA's answer might direct to (or even is) the answer.]

My question relates to these software: Hibernate3+Annotation, Spring MVC, MySQL and in this example also Spring Security.

I was wondering, why collections, which are automatically associated by Hibernate contain null values for each row number of the child table (besides the elements which are correct). My Example:

I have a users and an authorities table, the primary key of the users table is username which serves as foreign key. Right now, there are 13 rows in my authorities table. When I retrieve a user from the database (MySQL InnoDB) and Hibernate automatically retrieves the user's authorities corresponding to this mapping:

@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;
}

... I end up with a collection "authorities" containing 14 (0-13) elements of which only four are not-null (four rows in the database table belong to that specific user, so that is correct). As far as I realize, I am using Hibernate defaults for properties like Fetchmode etc. I am getting the user like this:

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

The logging information from org.hibernate.loader.loader correctly "mentions" four rows for the resultset. Still, the user created has the four correct elements plus ten null values in the Array. In my specific example, this results in this exception:

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

Upvotes: 3

Views: 4597

Answers (2)

Gareth Davis
Gareth Davis

Reputation: 28069

The answer lies in the @IndexColumn annotation. It is using the value of id as the array index, thus the number of elements in the Array is basically going to be the value of the highest ID in the Authorities table.

see the hibernate documentation on indexed collections

try removing the annotation.

Also just as a thought; have you considered using a Set for the mapping? it isn't strictly necessary, it just a bit more common form of mapping that's all.

Upvotes: 3

FoxyBOA
FoxyBOA

Reputation: 5846

I can recommend you check your data. If you have a missed indexes (id column in your case), then instead of missed id you'll get null in your array. I.e.

table authorities:
username id
bob 1
bob 3
bob 5

As a result you will have an array: {0=null, 1=bob, 2=null, 3=bob, 4=null, 5=bob}

UPDATE: I met the situation in two cases:

  1. Missed key values in indexed column id at authorities table (e.g. 0,1,3,4,5 - missing value 2. Hibernate will automatically add to an array value with key 2 and value null).
  2. Indexed values are in order, but select criteria filter part of them (e.g. your HQL similar to that "from user u join u.authorities a where a.id=2". In that case hibernate load a user, but in authorities array you will have only 3 values: 0 - null, 1 - null, 2 - authority with id 2).

Upvotes: 2

Related Questions