Hibernate @ManyToOne getId()会导致获取

时间:2012-11-23 09:29:18

标签: java hibernate jboss7.x

我有一个问题,一个非常简单的选择(SELECT h FROM Hero h,其中h.owner =:player)会导致n + 1问题。该查询触发每个英雄实体对游戏的选择。

首先我添加了fetch类型lazy,它在select期间删除了替代查询。在我的代码中,我只需要一次游戏即可获得id。这为每个实体再次触发了选择。

所以我添加了一个帮助的连接提取,但它导致了我不需要的连接!我怎么能告诉hibernate代理对象在没有获取整个实体的情况下给我id?

我尝试了那里的提示但没有成功:http://256stuff.com/gray/docs/misc/hibernate_lazy_field_access_annotations.shtml

来自hibernate的@AccessType和来自javax的@Access都没有区别。当我调用getId()时,将始终获取游戏。

任何想法我错过了什么?我经常需要这个,如果可以,我想避免加入。

问候, 马库斯

PS:我使用jpa2 + hibernate 4和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();

1 个答案:

答案 0 :(得分:1)

这只是hibernate中延迟加载方式的一个副作用。从本质上讲,对惰性对象的任何访问都会导致它被填充。它不是id的特殊情况。

我认为你实际上无法在不触发加载的情况下从游戏对象中访问ID。你可以做的是使用getIdentifier方法向hibernate询问对象的id。我相信这不会触发获取,因为hibernate只是查找它对象的元数据。

或者,您可以在执行查询时在英雄身边加载游戏ID。

E.g。

SELECT h, h.game.id FROM Hero h where h.owner = :player

不是在当前查询中找到你的英雄列表,而是返回一对对象列表,每对都有英雄和游戏ID。

ID在HQL中被特别处理,因此在尝试访问对象时不会触发您获取的提取或连接。