How to update a datastore entity with Objectify? - java

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

Related

What is the real life use case of #Cacheput?

I understand that #Cacheput calls the method no matter what and updates the result in the cache? Then why do we need this annotation in the first place if the method is called everytime?
Consider an API that would simply return certain data from a database using #Cacheable annotation. And if another api would update the same data in the primary data source, it would also need to update it in the cache. Here for 2nd API, you need to use #CachePut annotation to implement that.
Why do we need this annotation in the first place?
That's the syntactical expression, that you are telling the spring container to enable cache. It eventually override any with same key in cache.
Real life scenario
A product-refresh operation, where you want a specific product details to be re-calculated, if any change in price and then store that product in cache for any future reference. #CachePut eventually override any with same key in cache.
#Cacheput will only update the values that are stale and hence it calls the method every time to update the cache.

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 .

What is the best practice for updating database objects in Java Spring Hibernate project

I would like to update a field by a unique ID in a MySQL database.
First method: fetch the object (select * from) from the database using unique ID (by uniqueresult()), then set the desired value to object and saveOrUpdate is performed.
Second method is to write an update query in a DAO implementation (update table tab set tab.name=123 where..., executeUpdate()), also the same result.
Which is a good way to perform update operation and why?
Well if you are using Hibernate, why would you do it in native SQL when you can just use Hibernate Sessions's .get(), .load(), .merge() .update() methods.
Here's an example from Hibernate documentation to modify a persistent object:
DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
cat.setName("PK");
sess.flush(); // changes to cat are automatically detected and persisted
For further reading you can check Modifying persistent objects and Modifying detached objects sections in Hibernate documentation.
And according to the documentation :
The most straightforward way to update the state of an object is to load() it and then manipulate it directly while the Session is open.
I hope this answers both your questions Which is a good way to perform update operation and why?.
There is no "good way" to perform the update you want to. It entierly depend on your needs.
Both method work, but the first will permit you to update more than one field without having to modify your sql query. It will be the responsability of the developper to take care at the state of the object before calling the saveOrUpdate method.
The second method will ensure that no other field will be update in database.
Answer you on your future needs. Do you only need this field to be updated? Can it change in the future? What will be the inpact of both method on the application?
Then you will have your answer.

How to save an entity in GAE datastore only if it does not exist while preventing race conditions

I am trying to save an entity to Google App Engine Datastore only if it does not exist, if it does the thread should not continue.
Main issue is: I want to prevent any race conditions, such that if 2 threads are doing this at the same time only one would succeed in saving the entity.
I am not sure what is the best approach for this, would using Transactions work or one must rely on other solutions such as using Memcache
Please provide answer in low level API in java
Assuming that the both threads are trying to save an entity with the same key, then this code:
datastore.add(entity);
will do what you want. If an entity already exists in datastore with the same key, then .add() will throw an exception.
When calling Datastore from App Engine, the api is different. Use a transaction. First try to get() the entity to see if it's there. If not, put() the entity.
Here's some sample code that demonstrates transactions using the App Engine API:
https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/appengine/datastore/src/test/java/com/example/appengine/TransactionsTest.java

JPA merge in a RESTful web application with DTOs and Optimistic Locking?

My question is this: Is there ever a role for JPA merge in a stateless web application?
There is a lot of discussion on SO about the merge operation in JPA. There is also a great article on the subject which contrasts JPA merge via a more manual Do-It-Yourself process (where you find the entity via the entity manager and make your changes).
My application has a rich domain model (ala domain-driven design) that uses the #Version annotation in order to make use of optimistic locking. We have also created DTOs to send over the wire as part of our RESTful web services. The creation of this DTO layer also allows us to send to the client everything it needs and nothing it doesn't.
So far, I understand this is a fairly typical architecture. My question is about the service methods that need to UPDATE (i.e. HTTP PUT) existing objects. In this case we have these two approaches 1) JPA Merge, and 2) DIY.
What I don't understand is how JPA merge can even be considered an option for handling updates. Here's my thinking and I am wondering if there is something I don't understand:
1) In order to properly create a detached JPA entity from a wire DTO, the version number must be set correctly...else an OptimisticLockException is thrown. But the JPA spec says:
An entity may access the state of its version field or property or
export a method for use by the application to access the version, but
must not modify the version value[30]. Only the persistence provider
is permitted to set or update the value of the version attribute in
the object.
2) Merge doesn't handle bi-directional relationships ... the back-pointing fields always end up as null.
3) If any fields or data is missing from the DTO (due to a partial update), then the JPA merge will delete those relationships or null-out those fields. Hibernate can handle partial updates, but not JPA merge. DIY can handle partial updates.
4) The first thing the merge method will do is query the database for the entity ID, so there is no performance benefit over DIY to be had.
5) In a DYI update, we load the entity and make the changes according to the DTO -- there is no call to merge or to persist for that matter because the JPA context implements the unit-of-work pattern out of the box.
Do I have this straight?
Edit:
6) Merge behavior with regards to lazy loaded relationships can differ amongst providers.
Using Merge does require you to either send and receive a complete representation of the entity, or maintain server side state. For trivial CRUD-y type operations, it is easy and convenient. I have used it plenty in stateless web apps where there is no meaningful security hazard to letting the client see the entire entity.
However, if you've already reduced operations to only passing the immediately relevant information, then you need to also manually write the corresponding services.
Just remember that when doing your 'DIY' update you still need to pass a Version number around on the DTO and manually compare it to the one that comes out of the database. Otherwise you don't get the Optimistic Locking that spans 'user think-time' that you would have if you were using the simpler approach with merge.
You can't change the version on an entity created by the provider, but when you have made your own instance of the entity class with the new keyword it is fine and expected to set the version on it.
It will make the persistent representation match the in-memory representation you provide, this can include making things null. Remember when an object is merged that object is supposed to be discarded and replaced with the one returned by merge. You are not supposed to merge an object and then continue using it. Its state is not defined by the spec.
True.
Most likely, as long as your DIY solution is also using the entity ID and not an arbitrary query. (There are other benefits to using the 'find' method over a query.)
True.
I would add:
7) Merge translates to insert or to update depending on the existence of the record on DB, hence it does not deal correctly with update-vs-delete optimistic concurrency. That is, if another user concurrently deletes the record and you update it, it must (1) throw a concurrency exception... but it does not, it just inserts the record as new one.
(1) At least, in most cases, in my opinion, it should. I can imagine some cases where I would want this use case to trigger a new insert, but they are far from usual. At least, I would like the developer to think twice about it, not just accept that "merge() == updateWithConcurrencyControl()", because it is not.

Categories