Reputation: 155
When an object is written to database and the primary identifier (id
) is known, it can be retrieved by the code below:
MyObject myObject = session.get(Class<MyObject>, id);
It seems, there is another way similar to get()
method:
IdentifierLoadAccess<MyObject> ila = session.byId(Class<MyObject>);
MyObject myObject = ila.load(id);
I'm looking for a scenario which clarifies differences between them and describes the reason for having two similar methods for the same job in API.
same question can be asked about session.load()
and session.byId().getReference()
.
Edit 1:
According to API documentation:
session.get()
and session.byId().load()
return persistent instance with given identifier, or null if there is no such persistent instance.
session.load()
and session.byId().getReference()
might return a proxied instance that is initialized in demand.
Upvotes: 3
Views: 1859
Reputation: 154050
IdentifierLoadAccess
allows you to specify:
LockOptions
CacheMode
even specifying both of them at once:
Post post = session
.byId( Post.class )
.with( new LockOptions( LockMode.OPTIMISTIC_FORCE_INCREMENT) )
.with( CacheMode.GET )
.load( id );
The same for getting a Proxy reference via getReference(id)
.
So, they are more flexible than the standard get
or load
which only take the entity identifier.
Upvotes: 3
Reputation: 211
It's mostly used in polymorphic association/queries. assume you have an entity named User with the BillingDetails association. If BillingDetails was mapped with lazy="true" (which is the default), Hibernate would proxy the association target. In this case, you wouldn’t be able to perform a type-cast to the concrete class CreditCard (which is a subclass of BillingDetails) at runtime, and even the instanceof operator would behave strangely:
User user = (User) session.get(User.class, userid);
BillingDetails bd = user.getDefaultBillingDetails();
System.out.println( bd instanceof CreditCard ); // Prints "false"
CreditCard cc = (CreditCard) bd; // ClassCastException!
To perform a proxy-safe typecast, use load()
User user = (User) session.get(User.class, userId);
BillingDetails bd = user.getDefaultBillingDetails();
// Narrow the proxy to the subclass, doesn't hit the database
CreditCard cc =
(CreditCard) session.load( CreditCard.class, bd.getId() );
expiryDate = cc.getExpiryDate();
Note that you can avoid these issues by avoiding lazy fetching, as in the follow-ing code, using an eager fetch query
User user = (User)session.createCriteria(User.class)
.add(Restrictions.eq("id", uid) )
.setFetchMode("defaultBillingDetails", FetchMode.JOIN)
.uniqueResult();
// The users defaultBillingDetails have been fetched eagerly
CreditCard cc = (CreditCard) user.getDefaultBillingDetails();
expiryDate = cc.getExpiryDate();
Truly object-oriented code shouldn’t use instanceof or numerous typecasts. If you find yourself running into problems with proxies, you should question your design, asking whether there is a more polymorphic approach.
Upvotes: 0
Reputation: 76
The similarity between
MyObject myObject = session.get(Class<MyObject>, id);
and
IdentifierLoadAccess<MyObject> ila = session.byId(Class<MyObject>);
MyObject myObject = ila.load(id);
is that both uses the copncept of hibernate cache mechanism but difference comes in fetching the data from database i.e
When we use session.get(Class,id) data from database comes in cache and you can make changes on that data and will be reflected back in database, as hibernate internally maintains a time stamp cache. This time stamp cache records the time at which a particular Hibernate managed table got modified and before returning the data from entity cache it validate whether the result cache are older with respect to table modification time.
But in case of session.byId().getReference() hibernate uses the concept of natural id in which data from database comes in cache but only onces.If you do any changes on that data using session.save(entity object) approach hibernate will throw an exception and if you do manually modification of table(insert,update,delete) it will not be reflected back when you fetch the data again as it always get the data from cache without checking whether that table for that entity has been modified again or not.
In case of session.get() and session.load() if there is any change in database like (insert,delete,update) of record it will get reflected either in the form of record or null pointer exception if record gets deleted.But in case of session.byId().load() and session.byId().getReference() it will first get the record from database when you try to fetch first time then it will save those record in session and will be shown to user from session only if any (insertion,deletion,updation) occurs then it will not be reflected back
Upvotes: 1
Reputation: 956
The key difference between get() and load() method is that load() will throw an exception if an object with id passed to them is not found, but get() will return null. Another important difference is that load can return proxy without hitting the database unless required (when you access any attribute other than id) but get() always go to the database, so sometimes using load() can be faster than the get() method. It makes sense to use the load() method if you know the object exists but get() method if you are not sure about object's existence.
Upvotes: -1