Salandur
Salandur

Reputation: 6453

disable property/collection loading with hibernate

does anyone know how to prevent hibernate from loading a collection or many-to-one assocation?

i have a use case where i need to load an object, but the calling program can determine whether certain properties are loaded or not. the same goes for part of a collections: certain rows have to be fetched, others not.

domain classes:

public class SomeClass {
    private SomeClass parent;
    private Set<OtherClass> collection;
}

public class OtherClass {
    private Date startDate;
    private Date endDate;
}

public class Dao {
    public SomeClass loadClass(long id, boolean parents, boolean historicalData) {
         // load SomeClass
         // if parents == true, load parent, otherwise leave <null>
         // if historicalData == false, load OtherClass where endDate == <null>
    }
}

I have thought of 2 solutions, but I ont to now if its possible with an criteria or query.

Solution 1 is don't make the assocation from SomeClass to OtherClass and the parent/child relation in the hibernate configuration and load the assocation in the code.
Solution 2 is to define different mappings with different entity-names with serve the special cases.

In this case the caller can be in an other JVM or transaction, so the session is closed, thus lazy loading is not an real option.

Upvotes: 0

Views: 6968

Answers (4)

Maarten Winkels
Maarten Winkels

Reputation: 2417

Write an Criteria query and use the setFetchMode method to change the fetching behavior for the parent and createCriteria method to additionally query the collection.

Criteria c = session.createCriteria(SomeClass.class).add(Restrictions.idEq(id));

if (parents) {
  c.setFetchMode("parents", FetchMode.EAGER);
}
if (historicalData) {
  c.createCriteria("collection", Criteria.LEFT_JOIN)
   .add(Restriction.lt("date", date))
   .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
}
return c.uniqueResult();

...this is assuming the default setting is LAZY (as per Hibernate default).

It is no option in Hibernate to leave properties null that do have a value (in this case a many-to-one association. The field will hold a proxy that can be used to lazily load the referred object. If the code never touches the object, it will not get loaded.

The same is true for the collection: if not fetched, it will hold a collection-proxy (a hibernate class that implements a collection interface), which will only load the contents when invoked.

Upvotes: 1

BacMan
BacMan

Reputation: 436

I think #2 is the best solution. While I have not used this solution myself, I know of other developers who have with success.

Upvotes: 0

GreenieMeanie
GreenieMeanie

Reputation: 3610

Use @OneToMany(fetch=FetchType.LAZY) like the above poster said, but be aware that lazy fetching of Collections and Associations is the default fetch type in Hibernate 3.x.

Upvotes: 0

Kees de Kooter
Kees de Kooter

Reputation: 7195

You should leverage Hibernate's lazy loading features for this. You can annotate a collection like:

@OneToMany(fetch=FetchType.LAZY)

In that case Hibernate only loads the collection if you actually access it in code.

Upvotes: 2

Related Questions