updateFirst method not always saving the object - spring

updateFirst method of Spring Mongo Template is not always updating the mongo Db collection as expected.
(update request is fired by a save button in Front end ui , we see that a toast message appears saying table is successfully saved after save button is pressed and request is completed)
When few update requests are fired in sequential order one after another with no gap between updates, after few requests I can see that the data is no longer updated but there are no errors in logs.
Below is the method which updates the Database.
#Override
public void updateTable(Source source, Table table) {
log.debug("updating existing table " + table.getTableId() + " on source " + source.getSourceId());
source.setStatus(SourceStatus.InProcess);
Query q = query(where("_id").is(source.getId()).and("deleted").is(false).and("tables._id").is(table.getId()));
Update u = update("tables.$", table);
u.set("lastModifiedAt", source.getLastModifiedAt()).set("lastModifiedBy",
source.getLastModifiedBy()).set("errorInObject", source.isErrorInObject()).set(
"errorInChildObject", source.isErrorInChildObject()).set("errors", source.getErrors()).set(
"failedFields", source.getFailedFields()).set("status",source.getStatus());
template.updateFirst(q, u, Source.class);
}
I have logged queries fired to Mongo Db on spring boot application using properties file parameter and always update query that is being fired has proper values , but
when update works -- There is a log message that says "Saving object to database" just before the update query is fired.
when update does not work -- There is a log message that says "Saving object to database" just after the update query is fired , I think its writing to DB the previous update instead of current update.
MongoDB version -- 2.6.7
Spring Mongo Template Driver version -- 2.13.3
Spring Boot version -- v1.3.2.RELEASE
Can provide additional information if needed.

I have tried to dig deep into the issue and see that the issue occurs when I fire update commands to Db with no gap between them which some how is disrupting MongoDb's queue to process the update and some update is getting over written.
So I have added 500 ms delay to every update request before calling the updateFirst method and this fixed the issue now the update is preserved all the times even when the update requests are very frequent there is enough time to process the update.

Related

JPA #Version behavior when data is changed from unmanaged connection

Enabling #Version on table Customer when running the tests below
#Test
public void actionsTest1 () throws InterruptedException {
CustomerState t = customerStateRepository.findById(1L).get();
Thread.sleep(20000);
t.setInvoiceNumber("1");
customerStateRepository.save(t);
}
While actionsTest1 is sleeping, I run actionsTest2 which updates the invoice number to 2.
#Test
public void actionsTest2 () throws InterruptedException {
CustomerState t = customerStateRepository.findById(1L).get();
t.setInvoiceNumber("2");
customerStateRepository.save(t);
}
When actionsTest1 returns from sleeping it tries to update too, and gets a ObjectOptimisticLockingFailureException
Works as expected.
But if I run actionsTest1 and while it is sleeping I open a SQL terminal and do a raw update of
update customer
set invoice_number='3' where id=1
When actionsTest1 returns from sleeping, its versioning mechanism doesn't catch the case and updates the value back to 1.
Is that expected behavior? Does versioning work only with connections managed by JPA?
It works as expected. If you do a update manually, you have to update your version as well.
If you using JPA with #Version, JPA is incrementing the version column.
To get your expected result you have to write the statement like this
update customer set invoice_number='3', version=XYZ (mabye version+1) where id=1
Is that expected behavior?
Yes.
Does versioning work only with connections managed by JPA?
No, it also works when using any other way of updating your data. But everything updating the data has to adhere to the rules of optimistic locking:
increment the version column whenever performing any update
(only required when the other process also want to detect concurrent updates): on every update check that the version number hasn't changes since the data on which the update is based was loaded.
Hibernate automatically increases/changes the value in #Version mapped column in your database.
When you fetch an entity record, hibernate keeps a copy of the record of the data along with the value of #Version. While performing a merge or update operation, hibernate checks if the current value in of Version is still the same and matches the copy of entity fetched earlier.
If the value matches, it means that the entity is not dirty(not updated by any other transaction) else an exception is thrown.

Spring hibernateTemplete get not getting updated record value

When process is in execution a stored proc is called using Java standard callable statement, which updates the record in db.
Later in flow, using hibernatetemplate get method(passing entity Id object), instance of record is fetched.
The problem is this instance has old value for record columns, before update by stored proc happened.
Its probably happening because hibernateTemplalte was called earlier for same table to update the same record. But even then, if get method is called shouldn't it make a fresh call to db to get updated record.
I tried using flush, but still issue remains.
Any inputs would be appreciated.

How to prevent two users to edit one row from DB

i am using Spring/Hibernate/ZK. In one tab i get object from DB for editing by user, but second user can open the same tab and the same object for editing . I want to informed second user whit message like "This object is аlready open" and hide buttons for save.Тhus second user can see current data from DB to this object but can`t edint him.Is there a way to check session for this object or another way to do that.
The other answers mostly look at the database, but if all users use the same zk application to access the database, you could keep track of opened objects in the Composer or ViewModel (depending whether you use MVC or MVVM; I'll just call it controller).
Your controller would need a static list of objects that are currently modified. If a user requests to open an object that is not in the list, everything is fine and your controller enables the fields and save button. Otherwise, those are disabled and/or you display a message.
The tricky part is clearing objects from that list. If a user presses the save button, you just remove the object from the list. But what if the user doesn't and just closes the tab or their session just times out? In this case you need a callback, or a mechanism that regularly checks whether the screen is still open.
You could achieve this by adding a zk timer to the tab that pings every now and then and updates the timestamp in your static list (so make it a map). If a new user tries to edit the object, check how old the last timestamp is. If it is old enough (i.e. the previous user saved it or abandoned the screen), allow them to edit it.
Still, you have to think about what to do if a user just keeps the screen open. How long are they allowed to keep the lock on the object? This is an issue in Microsoft Office as well. If multiple users try to open an Excel file from a network location, the first one gets to lock and the others cannot save until that user saves.
You may have additional field which indicates that column is being edited. When first user starts work, the field would be updated. The second user would query object with 'on hold' status and your code would handle this.
Other way - use Hibernate #Version field in your entity. It holds object version which is incremented after every update operation. If second user would save object after first one already saved, it would throw OptimisticLockException which you could handle in your code. More about optimistic and pesimistic locking: Chapter 5. Locking. Related discussions: Hibernate Automatic Versioning and When to use #Version and #Audited in Hibernate?
The best solution is to use Optimistic Concurrency Control with Versioning and when Hibernate throws Concurrency Update issue due to same row is being updated in two transaction then use one of below strategy
First Wins Strategy
Last Wins Strategy
Merge Conflicting Update Strategy
First Wins Strategy is not good solution as it leads to lost update and user will get frustrated that all his work is lost.
By Last Wins Strategy one of user will get error message that you are working on Stale data and start your transaction again . By this way also user can get frustrated due to fact that now again he need to restart operation from beginning but his changes will not lost.
Instead go with Merge conflicting Update Strategy, when Hibernate throws Stale object exception reload screen with new data and user will see updated result and allow him to proceed with latest data. In this user changes will not loss and user will not get error message , just his screen reloads with fresh data and he can decide whether to proceed or not .
You can take example any e-commerce site and you will get one of result of either Last Wins Strategy or Merge Conflicting Update Strategy. Two user can start to by one item but one of user will get message in last screen that item is not stock.

spring hibernate merge example

I have a Spring 4 and Hibernate 5 back-end RESTful web-service. This works great and is all unit tested. The front-end is a SmartGWT 5.0p application which uses DataSources, not RestDataSources to communicate with the back-end.
The front-end SmartGWT 5.0p uses a listgrid to edit data, and then the ListGrid is attched to a datasource. Only the edited data in the ListGrid is sent back, not the entire row. If I could, I'd like to be able send backthe entire listgrid row with edited data, and the unedited data. If I could get an answer to that, that would be great.
Or, the alternate is we let SmartGWT only send back part of the data which is edited. This comes to the back-end as JSON and is changed into an Object/Entity. The controller/end-point is not in a session yet, but then we call a method in the service layer which is transactional.
So, then question becomes we have a detached object in a session in the method in the service layer. We have a detached object with a database primary key ... but it also has 1 or 2 fields of updated data, and now we want to merge that data back to the database. We can't call an update with this entity because with the partial data, some of the fields are being set to null. In reality, we want to pull back the item from the databae, update the edited fields, and then write the data back to the database.
I could do this all manually ... but do I have to? I expect there is a more graceful way to handle this.
Thanks!
This is only a partial answer:
I can make SmartGWT combine old values and new values with a link I found here:
SMARTGWT DataSource (GWT-RPC-DATASource) LISTGRID
And the code is as follows:
private ListGridRecord getEditedRecord(DSRequest request)
{
// Retrieving values before edit
JavaScriptObject oldValues = request
.getAttributeAsJavaScriptObject("oldValues");
// Creating new record for combining old values with changes
ListGridRecord newRecord = new ListGridRecord();
// Copying properties from old record
JSOHelper.apply(oldValues, newRecord.getJsObj());
// Retrieving changed values
JavaScriptObject data = request.getData();
// Apply changes
JSOHelper.apply(data, newRecord.getJsObj());
return newRecord;
}
This JSON string contains the new fields updated, and the old fields. When this json string is sent back to the RESTful back end, the Jackson Mapper creates an entity and puts all the fields in, this is essentially a detached entity. It's an object outside of the session, but the id resides in the database.
Because I have a complete entity, I can all an update, and that works.
Problem solved.
BUT, I'd still like to find out an elegant solution for taking a detached entity, get the original record from the database, and then merge these two objects, and then finally update the record.
In the Service layer in Spring which has a transaction, and creates the session,
a manual process, which I don't want to do might look something like this:
1) get the id from the updatedEntity
2) get that attachedEntity from the database using that id
3) compare the fields
if( updatedEntity.updateField1 != null )
{ attachedEntity.setField1(updatedEntity.updateField1) }
If I had to do step 3 for multiple fields,
that's not very elegant.
4) Update attachedEntity to the database, because it now has updated fields.
So, again, an elegant solution to fix this might be helpful. Thanks!

codeigniter session save to database keep updating many times

I have a question. I'm using latest version of CI.
I have currently enabled session to use the database, but there is only one problem with how it works since it tends to update the database every time you update your session.
Is there a way to fix that so that session would only update the database once before it destructs?!
I currently have around 9 update requests from one CI session only :) ! so any help would be lovely.
a simple Code example, my proccess is much more complicated than this, but just for demonstration purpose
Controller/auth [include post with true login]
function login(){
$trial=$this->user->attempt($this->input->post('user'),$this->input->post('pass'));
if($trial){
//1st update query
$this->session->set_userdata('user',$trial);
//Start intializing user
//2nd update query
$this->load->model('relations');//constructer will load user friends and save them to $this->session->set_userdata('relations',$rel);
//3rd update query
$this->load->model('settings');//construtor will load user settings and save them to settings
}
}
Above code will create 3 update request all targeted to update field userdata = current session.
my point is there is no need to update db every time we add something to session, its already saved in $_SESSION, so keep it there , and keep manipulating $_SESSION till end,
only updating user_data once at the end of all runtime -destructor- with the end result session is enough to save session to db.
please note that CI loads session from session using select * from ci_session (first request in picture) and then it just keep updating session repeatedly and pointless since it will not select it again during runtime !
so why not just LOAD it once session library is loaded. and save it just before it destruct. thats what im trying to accomplish.
Thanks
I have found a solution for this, get the existing user data from the session by using following code
$userdata = $this->session->all_userdata();
$userdata['fname'] = 'John';
$userdata['lname'] = 'Mulharn';
$userdata['email'] = 'Mulharn#john.com';
$this->session->set_userdata($userdata);
All this happens in 1 transaction instead of 3 database transaction.
Hope that helps.
A session may be updated by passing an array with all of the values, rather than doing them one at a time. Have another look in the Users' Guide

Resources