- Lazy fetching allows the fetching of a relationship to be deferred until it is accessed.
- "Lazy loading" means that an entity will be loaded only when you actually accesses the entity for the firsttime.
- This saves the cost of preloading/prefilling all the entities in a large dataset beforehand while you after all actually don't need all of them.
- Lazy setting decides whether to load child objects while loading the Parent Object.
The actual lazy loading is then done inside the methods of the
PersistentSet
which Hibernate uses "under the hoods" to assign the collection of entities as Set
.E.g.
public class Parent {
private Set<Child> children;
public Set<Child> getChildren() {
return children;
}
}
.
public void doSomething() {
Set<Child> children = parent.getChildren(); // Still contains nothing.
// Whenever you call one of the following (indirectly),
// Hibernate will start to actually load and fill the set.
children.size();
children.iterator();
}
- You need to do this setting respective hibernate mapping file of the parent class.Lazy = true (means not to load child)By default the lazy loading of the child objects is true. This make sure that the child objects are not loaded unless they are explicitly invoked in the application by calling getChild() method on parent. In this case hibernate issues a fresh database call to load the child when getChild() is actully called on the Parent object
- But in some cases you do need to load the child objects when parent is loaded. Just make the lazy=false and hibernate will load the child when parent is loaded from the database.
- Lazy loading is a design pattern commonly used in computer programming to defer initialization of an object until the point at which it is needed. It can contribute to efficiency in the program's operation if properly and appropriately used
ISSUES:
- The cost of retrieving and building an object's relationships, far exceeds the cost of selecting the object. This is especially true for relationships such as
manager
ormanagedEmployees
such that if any employee were selected it would trigger the loading of every employee through the relationship hierarchy. Obviously this is a bad thing, and yet having relationships in objects is very desirable.
USE:
- In JPA lazy fetching can be set on any relationship using the
fetch
attribute. - The
fetch
can be set to eitherLAZY
orEAGER
as defined in the FetchType enum. - The default fetch type is
LAZY
for all relationships except forOneToOne
andManyToOne
, but in general it is a good idea to make every relationshipLAZY
. - The
EAGER
default forOneToOne
andManyToOne
is for implementation reasons (more difficult to implement), not because it is a good idea.
Example of a lazy one to one relationship annotations
@Entity
public class Employee {
@Id
private long id;
...
@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name="ADDR_ID")
private Address address;
...
}
Example of a lazy one to one relationship XML
<entity name="Employee" class="org.acme.Employee" access="FIELD">
<attributes>
<id name="id"/>
<one-to-one name="address" fetch="LAZY">
<join-column name="ADDR_ID"/>
</one-to-one>
</attributes>
</entity>
Magic
- For
OneToOne
andManyToOne
relationships the magic normally involves some sort of byte code manipulation of the entity class, or creation of a subclass. - This allows the access to the field or get/set methods to be intercepted, and for the relationships to be first retrieved before allowing access to the value.
Serialization, and Detaching
- A major issue with lazy relationships, is ensuring that the relationship is still available after the object has been detached, or serialized.
- For most JPA providers, after serialization any lazy relationship that was not instantiated will be broken, and either throw an error when accessed, or return null.
- The naive solution is to make every relationship eager.
No comments:
Post a Comment