JPA save/update only if modifications - spring

I have a problem, with the Spring JPA, I did not find anything about saving entity only if there are modification. And I am not talking about saving certain fields.
After the database data is loaded by the JPA entity manager, how can I verify, before I save the entity, if there are modification/changes to the fields. Without taking each field and verify it with:
if (field != ...)
Class i = repo.findByExternalId(externalId);
...
if (modifications)
repo.save(i);
else
//don't save
I tried with dynamic-update=true but it doesn't work.
If you have some information about what to search on the web... that would be helpful as well.
Thanks.

Just don't call save() but put everything in one transaction.
JPA will do the checking for you and save changes if necessary.

Related

Why is my spring boot app creating another record in the database instead of merging them together?

AHere's the setup:
Springboot, springboot-data-jpa, hibernate.
I have one entity, a Review, that has a property that has a many-to-one relationship with another entity, a vehicle. The vehicle entity conversely has a one-to-many relationship with the review entity.
To create the review entity via a POST endpoint, I give the vehicle entity as of the properties in the JSON.
This works fine, not only is the review record added in the database but it goes ahead and creates the vehicle entity as well. The only issue is that in the case where the vehicle already exists, instead of making that connection, it creates another record with the exact same information so I have a duplicate vehicle entity.
Is this because I should be handling the creation of the vehicle entity on my own instead of relying on hibernate? Am I just missing some annotation I'm not aware of?
Originally I was getting an error about flushing or something so I added the Cascade.ALL annotation to the review class 'vehicle' property and that fixed that problem. I tried changing the Cascade type as it seems to be relevant somehow but it either breaks the server or doesn't work at all.

How to delete from db?

I am using Spring framework, the following code was use to delete a record, but it failed to worked, why?
List<PostAttachment> postAttachments = postAttachmentRepo.findByObjectKey(key, Sort.by(Sort.Direction.DESC, "createdAt"));
postAttachments.remove(0);
findByObjectKey is returning collection to you and
postAttachments.remove(0);
Will remove the record from the collection only and not from the database. So, to remove data from dabase either
You need to call entityManager.remove(postAttachments.get(0)), for this entity needs to be managed and transaction.
Use spring repository method, postAttachmentRepo.delete(postAttachments.get(0)) in this case, spring manags everything (transaction as well entity is managed).

How to actualize entity in Spring JPA? Actualize or create new one?

I'm wondering what is best practice to update JPA entity in Spring project - update original entity or create new? I see these two approaches:
Use original - Actualize necessary fields in original entity and save this updated entity back to the repository.
Use copy - manually create new instance of entity, set all field from original entity (+ updated fields) into new entity and save the entity back to the repository.
What approach do you use / is recommended? And why?
When it comes to updating, the standard way would be to retrieve the entity reference(read below) and make changes within a transactional method:
private JpaRepository repo;
#Transactional(readOnly = false)
public void performChanges(Integer id){
Entity e = repo.getOne(id);
// alter the entity object
}
Few things regarding the example:
You would want to use the getOne method of JpaRepository as much as possible as it is in general faster than the findOne of the CrudRepository. The only trick is that you have to be sure that entity actually exists in the database with the given id. Otherwise you would get an exception. This does not occur regarding the findOne method so you would need to make that decision regarding each transactional method which alters a single entity within your application.
You do not need to trigger any persist or save methods on the EntityManager as the changes will be automatically flushed when the transaction is commited.. and that is on method return.
Regarding your second option, I dont think thats much of a use as you would need to get the data using above method anyway. If you intend to use that entity outside of the transaction, then again you could use the one retrieved from the exmaple above and then perform merge once it is again needed within the transactional context and thus Persistence Provider.
Getting an entity and then just updating that entity is the easiest way to do that. Also this is faster than a creation of a copy since EntityManager manages an entity and know that managed entity already exists in DB (so no need to execute additional query).
Anyway, there is third and the fastest approach: using executeUpdate on Query object.
entityManager
.createQuery("update EntityName set fieldName = :fieldName where id = :id")
.setParameter("fieldName", "test")
.setParameter("id", id)
.executeUpdate();
It is faster due to bypassing the persistent context

spring JPA - delete by marking the entry

I would like to know if Spring or JPA has something implemented to take care of this problem.
In Entity Framework there is something similar with this.
When I want to delete an object, I don't want to remove it from the database. Instead I want to mark it as deleted by using a datetime field.

HibernateDAOSupport Get method

I am working on a existing project which uses Hibernate and Spring. I see a following code which uses HibernateDAOSupport class,
Employee emp = getHibernateTemplate().get(Emplyee.class, 1001)
After the above line we set some property like emp.setAge(25); and at the end we don't call any Save or SaveOrUpdate method. But it's saving the data to DB. How is it possible ?
If it can Save then what is the difference between getHibernateTemplate().get() and getHibernateTemplate().save/SaveOrUpdate methods ?
This is expected behaviour of Hibernate and it is because the Employee entity is loaded into the PersistenceContext and therefore enters the 'persistent' entity lifecycle state.
When you commit the transaction, Hibernate will check any 'persistent' entities within the PersistenceContext to see if they are "dirty". Dirty means that any values of the entity have changed. Your call to emp.setAge(25) means that Hibernate understands that data within the entity has changed (it is dirty), and it should therefore make the changes persistent when the transaction commits.
It is worth reading and understanding how Hibernate manages entity states as it can be a little confusing to start with. The documentation is here.

Resources