tags:

views:

285

answers:

3

I want to fetch the id of a one-to-one relationship without loading the entire object. I thought I could do this using lazy loading as follows:

class Foo { 
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    private Bar bar; 
}


Foo f = session.get(Foo.class, fooId);  // Hibernate fetches Foo 

f.getBar();  // Hibernate fetches full Bar object

f.getBar().getId();  // No further fetch, returns id

I want f.getBar() to not trigger another fetch. I want hibernate to give me a proxy object that allows me to call .getId() without actually fetching the Bar object.

What am I doing wrong?

A: 

You could use a HQL query. The getBar() method will truly return a proxy, that won't be fetched until you invoke some data bound method. I'm not certain what exactly is your problem. Can you give us some more background?

Bozhidar Batsov
Thanks for the response. What you describe is not what happens. getBar() is causing the fetch to occur. I would expect what you describe, that a proxy object is returned and no fetch is executed. Is there any other configuration I could be missing?
Rob
Actually the getId() following getBar() is causing the entity to be fetched. You're not missing any configuration IMO. Maybe some query like "select f.bar.id from Foo f where f.id=?" will do the trick for you.
Bozhidar Batsov
The proxy object should not fetch the full Bar on bar.getId(). It already knows the id, since that is part of Foo. Anyway, it executes the fetch without invoking .getId()
Rob
+2  A: 

Use property access strategy

Instead of

@OneToOne(fetch=FetchType.LAZY, optional=false)
private Bar bar;

Use

private Bar bar;

@OneToOne(fetch=FetchType.LAZY, optional=false)
public Bar getBar() {
    return this.bar;
}

Now it works fine!

A proxy is initialized if you call any method that is not the identifier getter method. But it just works when using property access strategy. Keep it in mind.

Arthur Ronald F D Garcia
+1  A: 

Just to add to the Arthur Ronald F D Garcia'post: you may force property access by @AccessType("property"), see http://256.com/gray/docs/misc/hibernate_lazy_field_access_annotations.shtml

Another solution may be:

public static Integer getIdDirect(Entity entity) {
    if (entity instanceof HibernateProxy) {
        LazyInitializer lazyInitializer = ((HibernateProxy) entity).getHibernateLazyInitializer();
        if (lazyInitializer.isUninitialized()) {
            return (Integer) lazyInitializer.getIdentifier();
        }
    }
    return entity.getId();
}
xmedeko