如何在会话结束后覆盖LAZY加载?

时间:2014-12-22 14:09:06

标签: java hibernate lazy-loading

我使用hibernate并尝试优化加载带有

注释的外部实体
@ManyToOne(fetch = FetchType.LAZY)

我不想在hibernate查询期间检索外部实体并使用LAZY获取类型。 稍后(在会话已经关闭之后),我想获得该外来实体但使用与hibernate不同的工具(另一个已经存储外部实体的缓存DAO(GuavaCache))。

但是,我立即得到了一个LazyInitializationException。

我无法用@Transient替换@ManyToOne注释,因为删除@MabyToOne后,遗留的HQL代码太多了。

有人建议让getter方法最终并且不要直接访问实体字段,而只是使用getter。这是一个例子:

    private int foreignId;

@Basic
@Column(name = "foregn_id")
public int getForeignId() { return foreignId;}
public void setForeignId(int id) { this.foreignId = id; }


// private DBForeignEntity foreignEntity;  no more sense to have this field

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "foregn_id", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
public final DBForeignEntity getForeign() {
    // return foreignEntity; deprecated usage! Hibernate will create proxy object and throw LazyInitException after session was closed
    return getFromCache(getForeignId());
}

public void setForeign(DBForeignEntity foreignEntity) {
    // this.foreignEntity = foreignEntity;   no more sence for having setter at all
}

这个丑陋的解决方案排除了任何持久嵌套实体的能力,因为不再有外国实体的设置者了!

是否有另一种解决方案来弃用Hibernate为我的实体创建代理对象? 如果会话关闭,如何避免LazyInitializationException? 在这种情况下,非代理是否有任何不良后果?

1 个答案:

答案 0 :(得分:0)

在当前情况下,hibernate代理只有子(foreignEntity)实体,而不代理当前(父)实体。因此,检查外部实体的实例并将其替换为自定义加载:

是没有问题的
private int foreignId;

@Basic
@Column(name = "foregn_id")
public int getForeignId() { return foreignId;}
public void setForeignId(int id) { this.foreignId = id; }

private DBForeignEntity foreignEntity;  

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "foregn_id", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
public final DBForeignEntity getForeignEntity() {
    if (foreignEntity instanceof HibernateProxy) {
        foreignEntity = getFromCache(foreignId);
    }
    return foreignEntity;
}

public void setForeign(DBForeignEntity foreignEntity) {
    this.foreignEntity = foreignEntity;   
}

此外,在调用

期间没有LazyInitException
DBParentEntity.getForeignEntity()