2

我正在使用播放框架和 JPA 和 Hibernate。

我有几个实体:

@Entity
public class Player extends Model {

    public enum Gender {

        MALE, FEMALE
    }

    @Required
    public String name;

    @Required
    public Gender gender;

    @Required
    public Long gold;
}

@Entity
public class Building extends Model {

    @Required
    @ManyToOne(fetch = FetchType.LAZY)
    public Player owner;

    @Required
    public String buildingType;

    @Required
    public Long buildingId;
}

@Entity
public class Stock extends Model {

    // Either a product type or a raw material
    @Required
    public Long goodId;

    @Required
    public Boolean isProduct;

    @Required
    public String image;
}

@Entity
public class Contract extends Model {

    @Required
    @ManyToOne(fetch = FetchType.LAZY)
    public Player player;

    @Required
    @ManyToOne(fetch = FetchType.LAZY)
    public Building building;

    @Required
    @ManyToOne(fetch = FetchType.LAZY)
    public Stock stock;

    @Required
    public Long ordersLeft;

    @Required
    public Long cyclesLeft;
}

有了这些实体,我想检索所有我的Contract和他们相关的BuildingStockPlayer

这是我使用的查询:

public static List<Contract> retrieveContractsForNewOrder() {
        return find("select distinct c from Contract c "
                + "left join fetch c.player "
                + "left join fetch c.stock "
                + "left join fetch c.building "
                + "where c.cyclesLeft = 0 and c.ordersLeft > 0").fetch();
    }

查询正在运行,我检索了我的Contract. 但是,buildingstock变量已加载但player变量未加载(对象中的类名ContractPlayer_$$_javassist_22并且它有一个名为 的处理程序JavassistLazyInitializer)。

我不知道我做错了什么以及为什么 Hibernate 在获取其他模型时拒绝获取玩家模型......

感谢您的帮助

编辑

经过一些测试,hibernate 执行的查询似乎是正确的:所有连接都在那里,所有模型的所有字段都在选择中。

但是结果很奇怪:我只是从Contractand Stock(不是从Buildingand Player)检索字段。

但是我Building的已经加载了,为什么?因为缓存?为什么BuildingPlayer没有出现在结果中?

编辑 2

我试图直接在 MySQL 中执行完全相同的请求,并且我正在检索我需要的所有变量,而 Hibernate 似乎跳过了一些变量(它们并不全部在结果中)。

发生了什么 ?

编辑 3

clear()我在进行查询之前尝试了会话缓存,你猜怎么着?已Player加载...

我尝试只加载Playerusing ,left join fetch但它仍然无法正常工作(但Building由于缓存而被加载)。Player's字段不在结果中。但是,一旦我清除缓存,Player's字段就会出现在结果中,并且Player会加载到我的Contract.

为什么清除缓存解决了这个问题?Player在缓存中?如果是这样,为什么它没有加载?我不明白会发生什么,但我不能只清除缓存,因为我需要在此之后进行很多其他查询,并且我需要它们的缓存。

4

3 回答 3

4

JPA 强制提供者缓存通过 EntityManager 读取的托管实体以维护对象身份,因此每次您在该上下文中查询实体或获取对它的引用时,您都会获得相同的实例。因此,如果您以一种在早期返回代理实例的方式读取实体,则该代理实例应该保留在缓存中,直到 EntityManager 被清除。所有后续查询都应​​返回对象的相同实例。

解决方案是在关键点清除或关闭并重新获取新的 EntityManager,然后确保根据需要加载对象的查询是在上下文中执行的第一个查询。

于 2013-09-06T15:36:01.987 回答
0

尝试更改为FetchType.EAGER

于 2013-09-01T19:34:42.663 回答
0

休眠中的枚举,作为枚举持续存在 关注已接受的答案。
对于像缓存这样的休眠相关概念,请阅读本教程。
http://www.youtube.com/playlist?list=PL4AFF701184976B25

于 2013-09-03T07:45:23.770 回答