updating object using saveOrUpdate in Hibernate - java

I am familiar with Hibernate.I have a question.
Lets say I do session.saveOrUpdate(object). If object contains some 'id'(object identifier), then it means update query will be fired if the object is modified.
I want to know how does Hibernate do that i.e. there could be 'n' number of fields in the object.Does Hibernate check each and every field to know if any field is modified(in this case update query to be fired)?

While using use .saveOrUpdate() it will check if the object has no identifier property and if so it will make it persistent by generating it the identifier and assigning it to session.
if the object is already persistent in this session, do nothing if
another object associated with the session has the same identifier,
throw an exception if the object has no identifier property, save() it
if the object's identifier has the value assigned to a newly
instantiated object, save() it if the object is versioned by a
or , and the version property value is the same
value assigned to a newly instantiated object, save() it otherwise
update() the object
From Hibernate Docs

It checks the field(s) mapped as the identifier for the given object, if the object doesn't have an identifier it calls Save() which INSERTS the object, if it does it calls Update() which UPDATES it

Basically in hibernate if you set object with unique identifier any how it is going to update the whole row by calling
session.saveOrUpdate();
or if unique identifier not found it insert the data.

Related

JPA declare an entity as not new to avoid duplication

my JPA implementation is EclipseLink 2.3.0. I get one object from a cache system, when I try to update an object that contains the object retrieved from cache, JPA saves a new record of that even if the object has id set.
I suspect that the problem is because we don't retrieve that object using EntityManager, in that case the object would be set not new. Is there a way to flag the object as not new in EntityManager even if I didn't retrieve it from there?
Thanks

Ormlite ignore field when calling createOrUpdate

Is there an annotation that I can apply to a field that when calling createOrUpdate and passing the object that the specific field will not be updated if the object already exists.
The use case is I have a creation date in my object (which is set to current time of Java object creation) but if the object already exists in the database I do not want the date to be updated but would want the other fields updated. Would it be better to do a query on the id (create if it doesn't exist) and then in my code just iterate through the other fields and do updates for any that are different.
Is there an annotation that I can apply to a field that when calling createOrUpdate and passing the object that the specific field will not be updated if the object already exists.
Hrm. No there isn't. One thing you could do is create a class which has the same fields but without the date field. Or you could have a base-class with all of the fields except the date field. Then have a sub-class which adds the date field. Both classes would save to the same table. You would save the one with the date object when you want to use it.
Hope this helps.
I did this by using readOnly attribute.
#DatabaseField(columnName = "last_value_date", readOnly = true)
private Date lastValueDate;
During the update, all readOnly attributes are skipped from update query.

Hibernate Serialize/Deserialize Object and save it

I have an Object of my POJO Class and I saved it on my Redis (NoSql) server as byte[].
Now I When I get the object back from the Redis server, make some changes and call session.saveOrUpdate(), it throws an exception.
a different object with the same identifier value was already associated with
the session
I am using SerializationHelper class to serialize() and deserialize() the object and its working fine.
Is there any way in Hibernate that I can save that deserialize object.
saveOrUpdate() tries to attach a detached (or transient) object to the session.
Since Hibernate guarantees that a session does never holds 2 instances of the same attached entity, it throws this exception.
If you want to copy the state of a detached object to an attached one, use session.merge() (which returns the attached, modified object).

In Hibernate, is there any difference between session.get() and session.load() besides how bad IDs are handled?

An application I'm working on does all its queries by identifier using session.load(). Given the chaos it causes when it can't find the identifier and throws an exception, I'm thinking of swapping it over to session.get(). But before I do that, it's such a fundamental part of the system that I want to make sure there's absolutely no other difference between the two methods. Is there any reason you can think of why the original developers would have chosen load() over get() aside from the handling of invalid IDs?
EDIT: As stated above, I'm fully aware that get returns false and load throws an exception. I'm asking if there's any OTHER way that they differ.
Isn't it so that Get never returns a proxy whereas Load does ?
http://ayende.com/Blog/archive/2009/04/30/nhibernate-ndash-the-difference-between-get-load-and-querying-by.aspx
I think that this is important:
Why is this useful? Well, if you know
that the value exist in the database,
and you don’t want to pay the extra
select to have that, but you want to
get that value so we can add that
reference to an object, you can use
Load to do so:
The code above will not result in a
select to the database, but when we
commit the transaction, we will set
the CustomerID column to 1. This is
how NHibernate maintain the OO facade
when giving you the same optimization
benefits of working directly with the
low level API.
From the NH 2.0 ref documentation:
Note that Load() will throw an
unrecoverable exception if there is no
matching database row. If the class is
mapped with a proxy, Load() returns an
object that is an uninitialized proxy
and does not actually hit the database
until you invoke a method of the
object. This behaviour is very useful
if you wish to create an association
to an object without actually loading
it from the database.
If you are not certain that a matching
row exists, you should use the Get()
method, which hits the database
immediately and returns null if there
is no matching row.
As usual, the best reference for this is the documentation:
Session.get():
Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance, or a proxy for the instance, is already associated with the session, return that instance or proxy.)
Session.load():
Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists.
You should not use this method to determine if an instance exists (use get() instead). Use this only to retrieve an instance that you assume exists, where non-existence would be an actual error.
So, the difference is the way that non-existing instances are treated.
A good approach is shown as follows
If you need to call a getter method, then use get method. get method hits the database.
public class AccountServiceImpl implements AccountService {
private SessionFactory sessionFactory;
public BigDecimal getBalance(Integer acountId) {
// You need to know your balance
// So you need to use get method to access the database
Account account = (Account) sessionFactory.getCurrentSession().get(Account.class, accountId);
return account.getBalance();
}
}
If you need to call both getter and setter method, use get method.
In response to ChssPly's comment:
JPA with Hibernate book says about load method
The load() method always tries to return a proxy, and only returns an initialized object instance if it’s already managed by the current persistence context.
And
It hits the database as soon as you try to access the returned placeholder and force its initialization
Thus, he is right when you set up a single property.
But There is the following scenario shown in JPA with Hibernate book
It’s common to obtain a persistent instance to assign it as a reference to another instance. For example, imagine that you need the item only for a single purpose: to set an association with a Comment: aComment.setForAuction(item).
If this is all you plan to do with the item, a proxy will do fine; there is no need to
hit the database. In other words, when the Comment is saved, you need the foreign key value of an item inserted into the COMMENT table.
The proxy of an Item provides just that: an identifier value wrapped in a placeholder that looks like the real thing.
regards,

Obtaining an object state

Does hibernate provide a method that returns an object's state (transient, persistent, detached)?
see Javadoc Hibernate Session and check the methods
contains - Check if this instance is associated with this Session.
getIdentifier - Return the identifier value of the given entity as associated with this session. Beware of the Exception that is thrown if the Entity is not associated, each Exception should be considered fatal and the Session should not be used after it
get - Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance.
i would use 'get' and furthermore check for changed values, after that its just an "saveOrUpdate" to persist or update (and re-attach) the actual object
Session.contains tells you if an object is associated with the session. If it has no identifier, it's transient, if it has an identifier and associated with the session, persistent. Identifier but not associated with a session, detached.
If that doesn't help, consider rephrasing your question with more context, that is, why do you need to know the state of an object in the first place?
I don't agree with a usage of session.contains(obj) to reveal hibernate object state. An object formerly persisted/loaded would be assumed as TRANSIENT after a simple call of session.clear() - if you got no primary key but a composite one you have no idea in which state it is ...
A correct approach can be found inside Hibernate 3: org.hibernate.engine.ForeignKeys.isTransient(...)

Categories