tags:

views:

638

answers:

4

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.

+2  A: 

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.

Kees de Kooter
i have no control over whether a property is accessed or not, because the object is returned to the client, with may run in an different JVM or transaction. I shall clarify that in the question.
Salandur
In that case I suggest you use a data transfer object that you populate based in your usecase.
Kees de Kooter
A: 

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.

GreenieMeanie
A: 

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

BacMan
A: 

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.

Maarten Winkels
i'm going with this solution. only need to document it, or manually set the properties that are not loaded to null.
Salandur