Search |
|||||
The innermost secrets of -javaagent:toplink-essentials-agent.jar revealedPosted by cayhorstmann on June 9, 2006 at 6:40 PM PDT
java -javaagent:toplink-essentials-agent.jar client.Client What is the reason behind that? Go to the GlassFish forum and search for javaagent. You'll get lots of confused queries. (Ok, most of them are mine.) The gist of the friendly advice that I got seemed to be that the toplink-essentials-agent.jar file was required for lazy loading. Lazy loading means that you can fetch an object from a database without also fetching all of its dependent objects. Here is the canonical example: In a multiple-choice testing application, a Question has a number of choices: @Entity
public class Question implements Serializable {
private int id;
private Collection<Choice> choices;
. . .
@OneToMany
public Collection<Choice> getChoices() {
return choices;
}
}
Now let's say we load a Question object from the database. Should all choices be loaded as well? And what about the objects that are related to Choice objects? That can be dangerous--suppose a Choice remembers all the questions that contain it? Clearly, something has to give, or we pull out a potentially huge transitive closure with every query. That's where lazy loading comes in. You can mark relationships so that they are fetched lazily. By default, collections are always fetched lazily. For example, consider this code: Question q = em.find(Question.class, id); System.out.println(q.getChoices()); System.out.println(q.getChoices().iterator().next()); It prints {IndirectList: not instantiated}
elvis.entity.Choice[id=1,text=run anywhere]
Clearly, our collection isn't a humble array list. Indeed, calling q.getChoices().getClass() reveals that it is a oracle.toplink.essentials.indirection.IndirectList. Ok, so I tried omitting -javaagent. What would happen to my lazy collection? Would it be eagerly fetched? Would my keyboard melt into a puddle of plastic if I accessed it? To my surprise, nothing special happened. The output was exactly the same. What, if anything, did the agent do?
We had a one-to-many relationship, so the agent didn't care. Let's add a lazily fetched one-to-one relationship: @Entity
public class Question implements Serializable {
. . .
private Choice answer;
@OneToOne(fetch=FetchType.LAZY)
public Choice getAnswer() {
return answer;
}
. . .
public String toString() {
return getClass().getName() + "[id=" + id
+ ",answer=" + answer"]";
}
}
Here we need to specify the fetch type since one-to-one relationship are eagerly fetched by default. Now we'll be able to tell the difference between running with -javaagent and without. Question q = em.find(Question.class, id); System.out.println(q.toString()); System.out.println(q.getAnswer());
Both outputs are interesting.
Without -javaagent, lazy fetching has been disabled. Why was the agent necessary? With the Collection<Choice> field, the persistence provider can simply set an object of a class that implements the Coll ection interface and that does the lazy loading. There is no need to modify the bytecodes of the class. But one can't do that with a single object. The Choice field must be set to a Choice object (or to null), and the getter must be modified. Mystery solved. Unfortunately, I haven't yet found a way to actually see the modified bytecodes, but if you set a breakpoint in the debugger and inspect the Question object in the debugger, you can see a field that was added to the class:
»
Comments
Comments are listed in date ascending order (oldest first)
|
|||||
|
|