JPA declare an entity as not new to avoid duplication - java

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

Related

JPA - update more fields on entity properly

I would like to do a simple update on a managed JPA entity on many fields.
First I query the entity which I would like to update:
MyEntity managedEntity = entityManager.createQuery(query).getSingleResult();
Then I need to update this entity with a new "MyEntity" object which is not managed by JPA:
MyEntity notManagedEntity = new MyEntity();
Of course it would be possible to read each field from notManagedEntity and set them to managedEntity which would do the update.
But is there a more elagant way to update the managed entity without needing to get and set every field one by one?
AFAIK, it's not a good idea to change a reference to a managed entity, because the persistence context will still reference the old entity, so any flush would trigger an exception... It's even more important when working with complex entities holding collections or ManyToOne references.
A related topic: What is the best way to update the entity in JPA
I would suggest to read the question:
Copy all values from fields in one class to another through reflection
This looks like the answer to your question. You then have to create a copy of the entiy you got from
MyEntity managedEntity = entityManager.createQuery(query).getSingleResult();
After you created the copy of you java object, you have to set the identifier from the entity an new value an inset this new Object to the persistent layer again.
From desinge perpective it looks a bit confusing, but if this is the request, at least from technical perspective it should work.

how hibernate manage serialization id while saving/fetching object in/from DB

As per my understanding to manage consistency serialization algo maintain one serialization id as private static final long serialVersionUID = 3170588813843556321L; in class while saving/fetching object from stream. and that id will be saved in that file/stream.
But with DB while we are NOT saving this in DB at all, so how hibernate check consistency during deserialization and throw java.io.InvalidClassException.
Please correct me if i am wrong at my understanding....
hibernate does not use serialization to store your classes into the database. it works by way of object relational mapping and (simplistically) maps every attribute of your object to a column in a table.
only if you have specific types of attributes (say public Image getImage()) will it store "real" binary - it might map this attribute to a blob to use serialization/deserialization to store/load the image attribute of your mapped class.
checking for data consistency in hibernate is done either via explicit locking (it locks the rows that make up your entity as long as your entity is in use) or via optimistic locking - where it will add a "version" field to your entity, update it every time you modify the entity, and use sql of the form "update table set ... where version=:myVersion" to ensure that no 2 processes modify the same entity at the same time.

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

Can I override generated IDs?

I'm using JPA 1, Hibernate and Oracle 10.2.0 and my entities are defined like this:
#Entity
#Table(name="TERMS")
public class Term implements Serializable {
#Id
#GenericGenerator(name = "generator", strategy = "guid", parameters = {})
#GeneratedValue(generator = "generator")
#Column(name="TERM_ID")
private String termId;
}
I have a situation where an XML representation of the Entity (and child entities) will be coming in through a web service to update/replace existing ones. My thought was to just delete the old ones and re-create it from the incoming XML.
However, doing a persist when my entities having existing IDs seem to make Hibernate very angry. So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?
Angriness from hibernate:
org.hibernate.PersistentObjectException: detached entity passed to persist: com.idbs.omics.catalog.entity.Term
Thanks
My thought was to just delete the old ones and re-create it from the incoming XML. However, doing a persist when my entities having existing IDs seem to make Hibernate very angry..
Indeed, you cannot assign an Id when it is supposed to be generated, at least not with Hibernate that won't consider the entity as new but as detached (the JPA specification is a bit blurry on the exact rules in this case but that's how Hibernate behaves, see 5.1.4.5. Assigned identifiers for more hints).
So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?
To make the delete/insert possible for the web service use case, you'd have to either:
not assign the id ~or~
use a special version of the entity without a generated identifier ~or~
use bulk operations(?)
The alternative if you're actually updating detached entities would be indeed to use a merge (but have a look at these previous questions just in case).
Which approach is better? I don't know, it think it depends on your needs. The later seems more natural if you're updating existing entities. With the former, you'd really get "new" entities (including a new value for the optimistic locking column). Depending on the exact implementation of the process, performances might also vary. And, by the way, what about concurrency (just to mention it, I'm not really expecting an answer)?
You can use EntityManager.merge to save an updated version of the entity. Be aware that this returns another object than the one you pass to it, because it basically fetches the entity from the database, updates the persistent properties from the object you pass and saves the persistent object.
See http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/ for more information on this problem.

Categories