Obtaining an object state - java

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(...)

Related

how to check if record exists using hibernate

I am new to hibernate. I am trying to implement a business rule where i need to check if a record exists in the database to continue different path based on the existance /not.
I am trying to ask if there is a light weight way to see if a record exists in database.
please point me to the documentation if there are some available.
Thanks for reading
When you know the primary key value, please take a look at EntityManager#find (http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#find(java.lang.Class,java.lang.Object).
More lightweight solution is use:
getReference
<T> T getReference(java.lang.Class<T> entityClass,
java.lang.Object primaryKey)
Get an instance, whose state may be lazily fetched. If the requested
instance does not exist in the database, the EntityNotFoundException
is thrown when the instance state is first accessed. (The persistence
provider runtime is permitted to throw the EntityNotFoundException
when getReference is called.)
getReference method are not required to be invoked within a transaction context

updating object using saveOrUpdate in Hibernate

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.

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).

Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Hibernate: different object with the same identifier value was already associated with the session
I have got almost the same problem like that user.
In my situation I load one entity from db, I convert this entity into a DataTransferObject, then I want to edit one attribute, after that I convert it back into an entityObject, then I update that entity and hibernate throws following error:
Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
Apparently, the problem is that the object I retrieve from db has the same id as the one I want to update (like it should be) BUT those are not the same objects!
How to manage that?
Thank you for help...
Your problem is that the object you previously loaded still exists in your hibernate session. I see two ways to cope with that.
1.) tell the hibernate session to merge your modified object with the one in the session
session.merge(object)
2.) kick the old object out of the session before writing the updated object to the session. session.clear() might work.
This is a very common problem with Hibernate. Even if you delete it from the session, the object will stay in Hibernate PersistanceContext and you will have the same problem. The problem is also coming from the fact that session.contains uses object equality, and not equals() to compare the object...
The story is the following: you have object A and object B,which are the same logical object, but two different objects in your java heap. and you have long time ago did something with object A in the session.
Now if you do session.delete(B) you will get the exception, because you are trying to delete an object which has the same primary key as A, but is not A.
The solution is simple:
Object findAAgain=session.merge(B);
session.delete(findAAgain);
the merge returns the instance of the object you have in the session first.
choose either one:
1 - you can close the session after loading the entity and open new session for update
2 - instead of creating new Entity for update, use the old one and edit it.
3 - detach your first entity from session - session.evict(myEntity)
Beyond just calling clear() on the session, it sounds like you might have a problem with the way you are using Hibernate:
Apparently, the problem is that the object I retrieve from db has the same id as the one I want to update (like it should be) BUT those are not the same objects!
Do you mean to say that you have two distinct entities which have the same ID? If so, then you should find a different field that uniquely identifies different entities.

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,

Categories