Paul Brinkley
Paul Brinkley

Reputation: 6353

"LazyInitializationException: could not initialize proxy - no Session" - in fact, no session to be found anywhere

I'm trying to debug pre-existing code making use of Hibernate and JPA. The error message makes sense, and even has several other questions on SO discussing it. But when I look for a session to keep open, I find that "session" is mentioned nowhere in the entire code body (aside from HTTP sessions - a completely different thing). Moreover, the code looks like it ought to work, which leads me to believe there is state information I can't see, but I cannot figure out what type of state I should try to look for.

I'll try to post a simple example, although I can't verify the following will do the same thing, due to all the dependencies involved. Hopefully it will suffice to say that the exception appears to be 100% reliably thrown, leading me to believe I'm merely overlooking something reasonably trivial.

The code acquires an instance of a class defined as follows:

@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
}

From this instance, another object is acquired, and an attribute is called on it in turn:

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

where OtherObject is declared as (partially) follows:

@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; }
    // ...
}

The LazyInitializationException occurs on the retrieval of the string from otherObject.

Why don't I get the LIE on the acquisition of someObject (it's acquired via some JPA code that I think is irrelevant here)?

I thought I could assume that since the first accessor probably results in a database query, which returns successfully, that the second one ought to as well. Is this incorrect?

Perhaps otherObject is "already here", and causes no query, whereas retrieving otherString is not. How can I test this? There is no code dealing with Session instances anywhere, and any calls to detach objects seem to occur in completely inapplicable locations. Should I look harder? Should I pursue the rabbit hole that getting Hibernate SQL logging to work in Tomcat appears to be?

Or is there no way to tell on what I've given here? Should I add more detail?

Upvotes: 0

Views: 984

Answers (1)

Kayaman
Kayaman

Reputation: 73558

Since otherObject is fetched lazily, when you execute getOtherObject() there is no database query. The lazy proxy object is returned. When you want to examine its contents, i.e. otherObject.otherString database access happens.

If you're not working in a transactional context (i.e. a session isn't open), you get LazyInitializationException. You can fix this by either fetching otherObject eagerly (how this is done depends on how you load the initial SomeObject) or by having a transaction/session open so the query can be executed lazily.

It's also not very hard to log SQL queries done by Hibernate.

Upvotes: 2

Related Questions