Pages

Tuesday 6 May 2014

Why should you never use @Access(AccessType.PROPERTY) in hibernate?

Hello!

Recently I discovered one decent pitfall regrading hibernate access type.


In short I got into big troubles having @Access(PROPERTY) with @ManyToOne association as well as with @OneToMany.
The mapping is usual :
@Entity
@Access(AccessType.PROPERTY)
public class Answer implements Serializable {
........................................
@ManyToOne(fetch = FetchType.LAZY, optional = false)
 @JoinColumn(name = "user", referencedColumnName = "user_id")
 public JuniorUser getUser() {
 return user;
 }
}
Hibernate developer expects this association to be retrieved lazily. So did I.
But to make it fetched lazily I had to spend a few days more.
It just turned out that the reason why hibernate always fetched JuniorUser eagerly is access type!
You might not believe me I tell you - do it youself!
The solution was to change access type to FIELD like: @Access(AccessType.FIELD)
And move my mapping annotations to field user.
This issue was tracked here!
And this is not the end about access type PROPERTY.
In another entity Topic I had @OneToMany association with above Answer entity. The mapping was simple:
@Entity
@Access(AccessType.PROPERTY)
public class Topic implements Serializable {
...........................
@OneToMany(mappedBy = "topic", fetch = FetchType.LAZY, orphanRemoval = true)
 @Cascade({ CascadeType.DELETE, CascadeType.SAVE_UPDATE, CascadeType.DETACH })
public List getAnswers() {
 return Collections.unmodifiableList(answers);
 }
}

The result is that hibernate always fetched my answers
collection together with topic. It means that whenever I loaded Topic entity I had all associated answers loaded as well. Hibernate logger printed query to get associated Answer entity as well it printed real values of my answer entities. The cause is of course @Access(PROPERTY) annotation.

My conclusion is that @Access(AccessType.PROPERTY) is dangerous and must be avoided!

No comments:

Post a Comment