1

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

首先,我添加了 fetch type lazy,它在选择期间删除了替代查询。在我的代码中,我只需要一次游戏来获取 id。这再次触发了对每个实体的选择。

所以我添加了一个有帮助的连接提取,但它导致了我不需要的连接!我如何告诉休眠代理对象在不获取整个实体的情况下给我 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();
4

1 回答 1

1

这只是休眠中延迟加载工作方式的副作用。本质上,对惰性对象的任何访问都会导致它被填充。它不会对 id 进行特殊处理。

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

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

例如

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

这将返回一个配对列表,而不是像当前查询那样为您找到英雄列表,每对都有英雄和游戏 ID。

ID 在 HQL 中被特殊处理,因此这不应触发您在尝试访问对象时获得的获取或加入。

于 2012-11-23T09:35:33.933 回答