cancel
Showing results for 
Search instead for 
Did you mean: 

JPA: Error "entity is detached" when executing a query

Former Member
0 Kudos

Hi experts,

I have two database tables with a foreign key constraint and generated JPA-entities for them:

@Entity

public class Verdeck implements Serializable {

@EmbeddedId

private VerdeckPK pk;

@Column(name="ID_VERDECK")

private String idVerdeck;

@OneToMany(mappedBy="verdeck")

@PersistenceContext

private Set<Uzsb> uzsbCollection;

...

}

@Embeddable

public class UzsbPK implements Serializable {

@Column(name="ID_UZSB")

private String idUzsb;

@Column(name="ID_PROJECT")

private BigDecimal idProject;

...

}

Furthermore I have a SessionBean implementing a query in one of its business methods:

@WebMethod(operationName="getVerdeckData", exclude=false)

public List<Verdeck> getVerdeckData (@WebParam(name="searchkey")

BigDecimal searchkey){

Query q = em.createQuery("SELECT v FROM Verdeck v WHERE v.pk.idProject = :searchkey")

.setParameter("searchkey", searchkey);

return q.getResultList();

}

When calling the method via WebService-Navigator I get this error:

"com.sap.engine.services.webservices.espbase.server.additions.exceptions.ProcessException: The relationship >>uzsbCollection<< of entity (com.karmann.r57schraub.jpa.Verdeck(idProject=57, idIntern=v1))cannot be loaded because the entity is detached"

(idProject / idIntern) is the composed key of "Verdeck" and (57 / v1) is a concrete value for this key in the database table.

If required I could give you classes VerdeckPK and UzsbPK as well.

Could you please explain what I'm doing wrong?

Thanks for each hint,

Christoph

Accepted Solutions (1)

Accepted Solutions (1)

Vlado
Advisor
Advisor
0 Kudos

Hi Christoph,

When you call the WS operation (method), the WS framework is trying to serialize the returned Verdeck objects, including their references. However, the field uzsbCollection has not been loaded by the JPA runtime because the default loading strategy for multi-valued relationships is LAZY. The solution is to explicitly specify it as EAGER:

@OneToMany(<b>fetch=FetchType.EAGER</b>, mappedBy="verdeck")

private Set<Uzsb> uzsbCollection;

(btw, I'm a bit concerned about the @PersistenceContext annotation here)

For more information on this subject, please refer to the following [article|https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/c0ffc32b-0dc9-2910-fd9c-a3e6f4c48e72].

HTH!

-- Vladimir

Former Member
0 Kudos

Hi Vladimir,

thank you for this hint! Especially for the article which provides the neccessary knowledge in background.

But using FetchType.EAGER does not solve my problem. I get a runtime error. In defaultTrace I get the following message

SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: com.karmann.r57schraub.jpa.Verdeck@f9ac24 -> com.karmann.r57schraub.jpa.Uzsb@1f2a70 -> com.karmann.r57schraub.jpa.Verdeck@f9ac24]->com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: com.karmann.r57schraub.jpa.Verdeck@f9ac24 -> com.karmann.r57schraub.jpa.Uzsb@1f2a70 -> com.karmann.r57schraub.jpa.Verdeck@f9ac24#

I already checked the records in my tables. There does not seem to be any cycle. Here's my test data:

VERDECK

ID_PROJECT ID_INTERN ID_VERDECK

57 v1 vext1

57 v2 vext2

UZSB

ID_PROJECT ID_UZSB ID_INTERN TYP_UZSB

57 ls1 v1 <null>

57 rs1 v1 <null>

57 sd1 v1 <null>

57 ls2 v2 <null>

57 rs2 v2 <null>

57 sd2 v2 <null>

Do you have any more idea?

Regards,

Christoph

Vlado
Advisor
Advisor
0 Kudos

Hi Christoph,

Actually, there is a cycle: Verdeck (57, v1) refers to Uzsb (57, ls1), (57, rs1), (57, sd1), which in their turn refer back to Verdeck (57, v1). Same with (57, v2).

The solution is to apply the javax.xml.bind.annotation.XmlTransient annotation on the getVerdeck() method in Uzsb (if you don't define get/set methods place the annotation on the verdeck field). This will cut off the cycle in the XML world.

HTH!

\-- Vladimir

Former Member
0 Kudos

Hi Vladimir,

great, this works!

Just another question. After having read the article you linked I believe to have understood the mechanisms of lazy and eager loading and why I need the eager loading. Nevertheless I'm not pleased to use eager loading because in real life this could lead to poor performance when loading large object structures.

My impression is that if I return DTOs (data transfer objects) to the caller instead entities, I could use lazy loading. If I do not return DTOs but entities, I am forced to work with eager loading. Is this right?

Kind regards,

Christoph

Vlado
Advisor
Advisor
0 Kudos

The short answer is yes. The long answer depends on the scenario. As long as the caller does not need the nested objects or they have been explicitly loaded (e.g. by accessing the collection while the containing entity is still managed), you can still use lazy loading with JPA entities as DTOs. In this case, however, the caller is the WS framework which does not understand JPA but talks simple Java objects and so tries to access a collection that has not been loaded, hence the PersistenceException.

HTH!

\-- Vladimir

Answers (0)