开发者

Programatically specify lazy loading for many-to-one in hibernate

I am using Hibernate 3.6 with Spring 3.0.5.

I have the following mapping for a User object

<class name="foo.User" table="FOO_USER">
    <id  column="USER_ID" name="id" type="java.lang.Integer">
        <generator class="identity"/>
    </id>


    <property name="firstName" column="FIRST_NAME" type="java.lang.String" length="100"/>
    ...
    <many-to-one name="organization" column="ORGANIZATION_ID class="foo.Organization" not-null="true" update="false" />
    ...

The User has a many-to-one relationship with Organization. Usually, I want that relationship to be eagerly loaded, so the mapping sticks with the default setting of lazy=false (by not specifying anything).

There is a certain case where I do not want to eagerly load the Organization. I tried specifying this with a Criteria

(User)getSession().create开发者_开发百科Criteria(User.class)
            .add(Restrictions.eq("id",id))
            .setFetchMode("organization", FetchMode.SELECT)
            .uniqueResult();

But the fetch mode is being ignored. Hibernate still eagerly loads the Organization relationship. I've been knocking my head against this for a few hours. Any help would be appreciated.


It's always best to leave associations mapped as lazy and use fetching strategies to tune performance. I don't believe there's a way to map something as lazy and then make it un-lazy in a particular instance. Certainly fetch=select won't do it, as that doesn't imply anything about laziness. See section 21.1 of "Improving Performance" in the reference manual for an explanation of the concepts.


FetchType can be set programatically using fetchProfiles

e.g.: Consider there is an Employee class and it has two child classes Address and Department Fetch profiles for these can be set in the Employee class.

@FetchProfiles({ @FetchProfile(name = "emp_address", fetchOverrides = { @FetchProfile.FetchOverride(entity = Employee.class, association = "addresses", mode = FetchMode.JOIN) }), @FetchProfile(name = "emp_department", fetchOverrides = { @FetchProfile.FetchOverride(entity = Employee.class, association = "departments", mode = FetchMode.JOIN) })}) public class Employee {

@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private Set addresses;

@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private Set departments; }

You can enable the fetchprofile When you are retrieve Employee record. If the fetch profile is enable then the child objects are eagerly fetch because you are doing a join

session.enableFetchProfile("emp_address");
session.enableFetchProfile("emp_department");
Criteria criteria = session.createCriteria(Employee.class); 
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
List employees = criteria.list();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜