Eclipselink does not detect a dirty entity - java

I was experimenting with eclipselink. I am trying to update an existing entity in database. The JPA entity only has public fields and fields are annotated with JPA annotation. The code loads an entity using EntityManager.find().
The code creates an instance of JPA entity, assigns value to public fields of the entity and invokes EntityManager.merge(entity) method. Eclipselink does not update database record. I enabled log to see whether Eclipselink issues SQL statement or not.
Eclipselink does not issue any update statement. Does this mean that even if I use field persistence, I can not assign value to public fields of the entity instead of using setter method?
Thanks,
Chir

Weaving introduces some optimizations such as lazy onetoone and manytones and change tracking. The only way these can work is if you use the accessor method on the entity, but if that isn't an option, you can turn them off as needed. See
http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_changetracking.htm
For details on change tracking.

Related

Hibernate entity with public fields instead of accessors

I'm using Spring Boot JPA Data with Hibernate under the hood. From quick testing it seems that using public fields instead of traditional getter/setter ceremony works fine. I was able to retrieve data, change field value and it was properly persisted back.
I expect slight performance degradation, because hibernate will be forced to compare all attributes at the end of transaction instead of some kind of dirty flag set in setters (although I'm not sure if it works like that).
Also I expect that lazy field values will not work (they need getter), though lazy collections should work.
According to Hibernate documentation:
The JPA specification requires this, otherwise, the model would prevent accessing the entity persistent state fields directly from outside the entity itself.
Although Hibernate does not require it, it is recommended to follow the JavaBean conventions and define getters and setters for entity persistent attributes. Nevertheless, you can still tell Hibernate to directly access the entity fields.
So it's not really clear to me which features depend on getters/setters presence.

Update by id of an entity attribute which is another entity

When I need to update a relationship of an entity, normally I have something like this:
XEntity entityToSave = ....
YEntity relatedEntity = relatedEntityRepository.findById(relatedEntityId);
entityToSave.setRelatedEntity(relatedEntity);
repository.save(entityToSave);
I would like to skip the findById of the related entity, because as I understand the id is everything what JPA should need to make the update.
So, I want like this:
XEntity entityToSave = ....
entityToSave.setRelatedEntity(
YEntity.builder().id(relatedEntityId).build()
);
repository.save(entityToSave);
Someway JPA should be aware that I just want to set the related entity (without update any attribute of it)
Do you know any way to achieve this?
UPDATE:
I want to avoid inject the relatedEntityRepository. As I have the id of the related entity. which is everything that jpa should know to update the relatioship
When using Spring repository, use getOne(..). It is Spring data equivalent to EntityManager.getReference(..). So like:
entityToSave.setRelatedEntity(repo.getOne(relatedEntityId));
Method getOne kind a "stores" a reference for entity by the id you provide. It does not fetch the entity - so it is lazy - until you access properties of referenced (your relatedEntity) entity (except id that is not needed to fetch anyway).
When referencing (your related) entity is saved then reference to referenced entity is saved also and usually without ever fetching the referenced entity (so if you do not modify referenced entity).
See this also
There usually just is no point to "avoid injecting" something especially singleton (Spring default) beans. You could achieve this behavior with #Modifying and some native query on repository method or make it a bit "lighter" by injection entity manager and use that to handle all the stuff but it would be more complex and obfuscating so IMO you would shoot your own leg that way.

Can I use saveOrUpdate method with DynamicUpdate annotation?

Hello I'm new to Hibernate.
Can I use saveOrUpdate method with DynamicUpdate annotation on entity class?
Can someone who can explain to me when should I use saveOrUpdate, save and update methods? Or whaat are the advantages and disadvantages?
DynamicUpdate is used when you to have the UPDATE statement include only the columns that have been changed, as opposed to all entity columns.
If the entity is already associated to the current Session (like when loading it using Session.get() or Session.load()), the dirty checking mechanism will automatically detected any change and issue the UPDATE on flush time.
The save is used to change the entity state from TRANSIENT to PERSISTED and it's only useful when you are saving new objects into the database.
The 'update' method is used to re-associate a detached entity.
The saveOrUpdate combines both these methods, but again this is only meant when the entity in question is not yet associated to the current Session. This method makes the entity managed so that Hibernate can automatically synchronize the entity with the associated database row.

Creating an UPDATE RETURNING query in Hibernate

In Oracle we can create an update query that will return the updated record using the RETURNING clause.
Is there similar functionality in Hibernate?
Apart from database-generated values there is obviously no need for Hibernate to return the updated instance because the object passed to Session.saveOrUpdate() is the updated instance. Database-generated values (sequence, trigger, defaults, etc.) will be set after Session.saveOrUpdate if they are accordingly annotated (or defined in a XML mapping file).
For identifier values use the JPA #javax.persistence.GeneratedValue annotation in conjunction with the JPA #javax.persistence.Id annotation. For simple properties use the native Hibernate #org.hibernate.annotations.Generated annotation (afaik there is no according JPA annotation).
How generated identifier values are retrieved by Hibernate depends on the generation strategy and/or the database dialect. For simple properties Hibernate executes an additional SELECT by id statement after the INSERT or UPDATE.

Does Hibernate Envers creates revision to audit tables if you update without changing any field values?

I am currently testing hibernate envers and I am confused with its behavior. Sometimes when we do updates without doing any changes, it does not record an audit. But currently, it does. Just like to make sure.
This can occur if Hibernate does not have access to the old state of the entity to compare to the new state. This typically occurs with when persisting detached entities. When there is no old state to compare, Hibernate assumes that the audited property has changed and logs a revision.
You can get around this issue by re-attaching detached entities using the merge() method before persisting the entity.
From my experience, it only creates an entry in the revision table if you have made changes to the entity.

Categories