我正在尝试使用Hibernate和JPA调试现有代码。错误消息是有道理的,甚至在讨论它时还有其他几个问题。但是,当我寻找一个保持打开状态的会话时,我发现在整个代码主体中都没有提到“会话”(除了HTTP会话,这是完全不同的东西)。而且,代码看起来应该可以工作,这使我相信有些状态信息是我看不到的,但是我无法弄清楚应该尝试寻找哪种类型的状态。

我将尝试发布一个简单的示例,尽管由于所涉及的所有依赖关系,我无法验证以下内容是否会执行相同的操作。希望足以说出该异常似乎是100%可靠地抛出的,这使我相信我只是忽略了一些相当琐碎的事情。

该代码获取一个定义如下的类的实例:

@Entity
@Table(name = "some_object")
public class SomeObject {
    @Valid
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "other_object_id")
    private OtherObject otherObject;
    // ...lots of other declarations
    public OtherObject getOtherObject() {return this.otherObject;}
    // ...lots of other accessors
}


从这个实例中,获取另一个对象,并依次在其上调用属性:

OtherObject other = someObject.getOtherObject();
String strVal = otherObject.getOtherString();


其中,OtherObject被声明为(部分)如下:

@Entity
@Table(name = "other_object")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class OtherObject {
    @NotEmpty
    @Column(name = "other_string")
    private String otherString;
    // ...
    public String getOtherString() { return this.otherString; }
    // ...
}


LazyInitializationException在从otherObject检索字符串时发生。

为什么在获取LIE时没有得到someObject(它是通过我认为与此处无关的一些JPA代码获取的)?

我以为我可以假设,因为第一个访问器可能会导致数据库查询(该查询成功返回),所以第二个访问器也应该如此。这不正确吗?

也许otherObject是“已经在这里”,并且不会引起查询,而检索otherString不会。我该如何测试?没有代码可以在任何地方处理Session实例,并且对detach对象的任何调用似乎都发生在完全不适用的位置。我应该看起来更努力吗?我是否应该寻找让Hibernate SQL日志记录在Tomcat中工作的麻烦呢?

还是没有办法告诉我我在这里给的?我应该添加更多细节吗?

最佳答案

由于otherObject是延迟获取的,因此当您执行getOtherObject()时,没有数据库查询。返回惰性代理对象。当您要检查其内容时,即发生otherObject.otherString数据库访问。

如果您不在交易环境中工作(即会话未打开),则会得到LazyInitializationException。您可以通过急于获取otherObject(如何完成取决于您加载初始SomeObject的方式)来解决此问题,也可以通过打开事务/会话以使查询可以延迟执行来解决。

记录由Hibernate完成的SQL查询也不是很难。

09-28 01:32