我正在尝试使用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查询也不是很难。