Best Practice for Making Sample/Preview Changes to JPA Entity - java

I have a web app backed by spring boot/jpa within which users can upload a file via the UI to make changes to JPA entities. I would like to return those changes as a 'preview' to the UI, without actually updating the database. I'm wondering what's considered the best practice for manipulating these JPA entities without actually making updates to the database until the user has approved the changes ... gather these records via CRUD to update? Pull the entity and then detach to manipulate and return? Return an updated clone?

Create a DTO(Data transfer object) with the fields that you need to preview, and when the user approve the changes, then use that DTO to update the database.

Related

Efficient database synchronization between clients - server in 2019

I need to keep in sync Client with postgreSQL database (only data that are loaded from database, not entire database, 50+ db tables and a lot of collections inside entities). As recently I have added server based on Spring-REST API to my application I could manage those changes maybe differently/more efficient that would require less work. So untill now my approach was to add psql notification that triggers json
CREATE TRIGGER extChangesOccured
AFTER INSERT OR UPDATE OR DELETE ON xxx_table
FOR EACH ROW EXECUTE PROCEDURE notifyUsers();
the client then receive the json built as:
json_build_object(
'table',TG_TABLE_NAME,
'action', TG_OP,
'id', data,
'session', session_app_name);
compare if this change is made by this client or any other and fetch the new data from database.
Then on client side new object is manually "rewritten", something like method copyFromObject(new_entity) and variables are being overriden (including collections, avoid transient etc...).
This approach requires to keep copyFromObject method for each entity (hmm still can be optimized with reflections)
Problems with my approach is:
requires some work when modifying variables (can be optimized using reflections)
entire new entity is loaded when changed by some client
I am curious of Your solutions to keep clients in sync with db, generally I have desktop client here and the client loads a lot of data from database which must be sync, loading database takes even 1min on the app start depends on chosen data-period which should be fetched
The perfect solution would be to have some engine that would fetch/override only those variables in entities that was really changed and make it automatically.
A simple solution is to implement Optimistic Lock? It will prevent user from persisting data if the entity was changed after the user fetched it.
Or
You can use 3rd party apps for DB synchronization. I've played some time ago with Pusher and you can find an excessive tutorial about Client synchronization here: React client synchronization
Of course pusher is not the only one solution, and I'm not related to the dev team of that app by at all.
For my purpose I have implemented AVL Tree based loaded entities and database synchronization engine that creates repositiories based on the loaded entities from hibernate and asynchronously search throught all the fields in entities and rewrites/merge all the same fields (so that if some field (pk) is the same entity like the one in repository, it replaces it)
In this way synchronization with database is easy as it comes to find the externally changed entity in the repository (so basically in the AVL Tree which is O(log n)) and rewrite its fields.

How to properly update entities using REST and JPA/Hibernate

I have entity Document, which has lots of columns, one-to-one, one-to-many and many-to-many mappings to some other entities.
Example:
Document:
id,
title,
body,
authors,
viewers,
...
Using REST, I want to update some particular document, controller receives serialized Document object, calling EntityManager's merge method persists null results to the database if controller received for instance only body , then I want the body to be updated only, but merge deletes records for title, authors and viewers and etc.
I understand that it is a standard behavior of EntityManager, but I am asking what is the most preferred technique to do updates on entities without receiving whole entity from front-end or some other endpoint. Should I load the entity from database using the id I received and set MANUALLY all of the fields and then save to database or should I use another technique.
I don't have any problem with writing manually all of the setters to copy the changes, but entities are really big in size with lots of relations. Asking for best practice in this case.
I know about DTOs but I want alternate approach when using entities for controllers and service methods.
For entity partial update, you will need to use either criteria api or jpql ... if you are using older versions with no criteria update or old query parser where jpql update is not allowed you will have to read from database first, update then insert again .... you can also make use of updatable=false for columns that should be only set on creation (like CREATION_DATE) and there is also a nice feature in hibernate called #DynamicUpdate which I haven't tried but looks brilliant ... It only updates the modified field (check Vlad's post here) ... concerning the DTO DP , I you might always need to use if you want to hide / modify some data from the client regardless to the way you store the data ... and it's always a good way to separate concerns (but comes with the mapping headache between domain & DTO objects which is much released thanks to spring converters)
There are two options one is update query, which works fine but you may feel
you are loosing some hibernate features and simplicity of the code. Else you can do it in Hibernate way like below
AuditorBean auditorBean = (AuditorBean) session.get(AuditorBean.class, AuditorBean.getId());
auditorBean.setFirstName("aa");
auditorBean.setLatName("bb");
auditorBean.setTrainLevel("ISO");
auditorBean.setAccessLevel(4);
Here you should not call any method like saveOrUpdate() or merge().
object is attached with transaction, so object is flushed and committed at the end of the transaction automatically .

How to update a datastore entity with Objectify?

I use the Google App Engine datastore and I need to update one my entities which has been saved on it (I use the Objectify framework to perform operations on the datastore).
However, I only need to update one field of the entity.
For now I load (calling load()) the entity, use a getter/setter to modify the field and then call save() to persist it. I am sure there is a better way. What is the preferred method to do so?
That's normal way.
I guess you're looking for SQL-like UPDATE? Google Datastore doesn't have such things. Update and Insert are same operation - you're putting an Entity for a key.
See docs: https://cloud.google.com/appengine/docs/java/datastore/entities#Java_Updating_an_entity

Java Spring application Database triggers auditing - how to provide the right user that made the change

We are developing a new web application. one of the most basic requirement is to audit all entities changes into a separate table.
We would like to use DB triggers for that purpose.
We use MySQL as our RDMBS.
The problem we now foresee is that whenever a trigger is pulled, and insert a new entry for the DB, it cant possibly know the (applicative) user that made the change. (all users have different ids, but spring uses a single user account for the db manipulations.)
Any ideas how to resolve this issue?
We resolved the issue by adding a field to all tables that are being audited of the userId, and on each CRUD operation we made it mandatory to provide it. (for system business logic we use id=0). this way our audit table are being populated with the id itself to be monitored.

Securing a Multi tenant SaaS application

I'm multing a multi-tenant SaaS web-application in Java, Spring, Struts2 and Hibernate. After a bit of research, i choose to implement multi-tenancy in a shared db, shared schema, shared table approach. And tagging each db-line with a tenantId.
I have rewritting my application, so Managers and Dao's will take the tenantId as a parameter to only serve the correct db-resources.
This works perfect for all view's when getting information. And also for creating new stuff (using the logged in users tenantId to store the info).
However, for updating and deleting stuff I am not sure how to secure my application.
For example: When a user want to edit an object, the url will be: /edit?objectId=x
And this is mapped to an action that will retrieve this object by Id. Meaning any logged in user can by url-modification view any object.
This i can solve by adding the tenantId to the Dao so if the User tries to view an object outside his tenancy he will get nothing.
Ok thats ok then, but about when sending in the edit-form?
What if the user modifies the request, messing with the hidden field objectId so the action will receive a request to alter an object not belonging to the users tenancy.
Or if the users url-modifies a delete action /delete?objectId=x
Basicly I need some way of assure that the logged in user has access to whatever he is trying to do. For all get's its easy. Just putting the tenantId in the where clause.
But for updates and deletes i'm not sure what direction to go.
I could query the db for every update and delete to see if the users has access to the object, but i'm trying to keep db-interaction to the minimum. So i find it impractical to make an extra db-call for every such action.
Does anyone have any hints or tips to my issues?
The same for reading applies to writing/updating: user can only see/access/change what they own. Your question is more about database that about anything else. The same constraints you apply to viewing data must also apply to writing data.
In this case, you don't want to wear the performance of a query first then an update. That's fine, since you can update the database with conditions. Since this seems likely to be database-level in your case you need to know what your database is capable of (to do it in one go). For example, oracle has the merge statement.
I am quite late to this thread and maybe you have already built the solution you were asking here about. Anyway, I have implemented a database-per-tenant multitenant web application using Spring Boot 2 and secured the web access using Spring Security 5. The data access is via Spring JPA (with Hibernate 5 as the JPA provider). Do take a look here.

Categories