I have the Problem that a quite simple select (SELECT h FROM Hero h where h.owner = :player) causes a n+1 Problem. The query triggers the select to the game for each hero entity.
First i added fetch type lazy which removed the alternative queries during the select. In my code i need the game only once to get the id. This triggered the select again for every entity.
So i added a join fetch which helped, BUT it causes a join i don’t need! How can i tell the hibernate proxy object to give me the id without fetching the whole entity?
I tried the tips there without success: http://256stuff.com/gray/docs/misc/hibernate_lazy_field_access_annotations.shtml
Both @AccessType from hibernate and @Access from javax make no difference. The game will always be fetched when i call getId().
Any Ideas what i am missing? I would need this quite often and i would like to avoid joins if i can.
greetings,
markus
PS: I use jpa2 + hibernate 4 with jboss 7.
@Entity
@NamedQueries({
@NamedQuery(name = "Hero.findByPlayer", query = "SELECT h FROM Hero h JOIN FETCH h.game where h.owner = :player")
})
public class Hero extends GameCharacter implements Serializable {
@ManyToOne
private Player owner;
@Entity
public abstract class GameCharacter extends GameObject implements Serializable {
... nothing special in here
}
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class GameObject implements Serializable {
@Id
private String id = java.util.UUID.randomUUID().toString();
@ManyToOne(fetch=FetchType.LAZY)
protected Game game;
@Entity
public class Game implements Serializable {
private static final long serialVersionUID = 4379242677193301727L;
@Id
private String id = java.util.UUID.randomUUID().toString();
This is just a side affect of the way lazy loading in hibernate works. Essentially, any access of the lazy object will cause it to populate. It doesn’t make a special case of the id.
I don’t think you’re actually going to be able to access the ID from the game object without triggering the loading. What you can do is ask hibernate for the id of an object using the getIdentifier method. I believe this will not trigger the fetch as hibernate is simply looking up the metadata it has for the object.
Alternatively you can load the game id alongsite the hero when executing your query.
E.g.
Rather than finding you a list of heros as your current query does, this will return a list of pairs, each pair having the hero and the game id.
ID is treated specially in HQL so this shouldn’t trigger the fetch or join you’re getting when trying to access the object.