Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate one-to-one: getId() without fetching entire object

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?

like image 586
Rob Avatar asked Apr 07 '10 15:04

Rob


People also ask

What is the difference between get() and load() of Hibernate?

From the output it's clear that get() returns the object by fetching it from database or from hibernate cache whereas load() just returns the reference of an object that might not actually exists, it loads the data from database or cache only when you access other properties of the object.

What is the difference between get() and load() methods of Session object?

In hibernate, get() and load() are two methods which is used to fetch data for the given identifier. They both belong to Hibernate session class. Get() method return null, If no row is available in the session cache or the database for the given identifier whereas load() method throws object not found exception.

What is the default fetching strategy in hibernate?

By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.

What is Many to Many mapping in Hibernate?

Many-to-Many mapping is usually implemented in database using a Join Table. For example we can have Cart and Item table and Cart_Items table for many-to-many mapping. Every cart can have multiple items and every item can be part of multiple carts, so we have a many to many mapping here.


2 Answers

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.

See: Hibernate 5.2 user guide

like image 126
Arthur Ronald Avatar answered Sep 23 '22 00:09

Arthur Ronald


Just to add to the Arthur Ronald F D Garcia'post: you may force property access by @Access(AccessType.PROPERTY) (or deprecated @AccessType("property")), see http://256stuff.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(); } 

Works for detached entities, too.

like image 27
xmedeko Avatar answered Sep 22 '22 00:09

xmedeko