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?
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.
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With