I know that transient instance means the instance is newly created and its corresponding row does not exist in the database where as detached instance has corresponding entr
It sounds like you're looking for EntityManager#contains(Object).
Check if the instance is a managed entity instance belonging to the current persistence context.
In order to check if object e is in :-
Persistence Context :- EntityManager.contains(e) should return true.
Detached State : PersistenceUnitUtil.getIdentifier(e) returns the value of the entity’s identifier property.
Transient State :- PersistenceUnitUtil.getIdentifier(e) returns null
You can get to the PersistenceUnitUtil from the EntityManagerFactory.
There are two issues to look out for. First, be aware that the identifier value may not be assigned and available until the persistence context is flushed. Second, Hibernate (unlike some other JPA providers) never returns null from Persistence- UnitUtil#getIdentifier() if your identifier property is a primitive (a long and not a Long).
What Matt suggested would only check if the given object is transient or associated with some entity manager.
If you want to check if it's detached or transient (which you shouldn't really care about! it should be transparent) you need to check if the given object has an ID.
if(data.getID() == null) return TRANSIENT;
The ID should only be set for persistent/detached objects. If for some reason you are setting the ID yourself on transient objects then I don't think what you want to do is possible.
If you don't know which field is the ID (for some reason) or you want to make it generic you can try:
ClassMetadata metadata = HibernateUtil.getSessionFactory().getClassMetadata(data.getClass());
if(metadata.getIdentifier(data) == null) return TRANSIENT;
You can try pass a transient object and a detached object to hibernate session update method and watch the difference.For transient object, hibernate will report an error.
So hibernate knows the object is transient or detached. But how? The answer is simple: hibernate will do an select before the update to get the information of which fields are dirty. If the object is transient, the will be no result of that selection operation then hibernate knows this is transient object and report an error.
Or, if you use @SelectBeforeUpdate(false)
, hibernate will not do the select, instead with an update directly, in this case, jdbc will report error due to the row need to update is not exist.
Of course you can check the id field if it generated by database or else the only way to know its state is do an query: not found means transient.
As others said, org.hibernate.Session.contains(Object)
may be used in Hibernate to know if an entity instance is attached or detached. Regarding the transient state, the best that could be done I think is what org.hibernate.Session.saveOrUpdate(Object)
(by virtue of org.hibernate.persister.entity.AbstractEntityPersister.isTransient(Object, SessionImplementor)
) does, that is:
@Id
property, it's always considered transient@Id
property value which is null
, it's always considered transient@Id
property value which is equal to the configured unsaved-value
, then it's considered transient (only applies to XML mapping, I think it's somewhat deprecated, see here)@Version
property whose value is the one of a newly created instance (that is, it's a null
Long
, or Date
, etc.), then it's considered transientHence, I think that, for entities without a generated id, looking at the @Version
property is the way to go. If there's no such property, Hibernate itself in saveOrUpdate
makes a SELECT query against the database to determine whether the entity instance is transient or not, to determine if it should do an INSERT or an UPDATE respectively.
See Hibernate manual (as an example, 4.3 one here).