I have a very basic question in saving objects which I get from a client sent via JSON.
I have a customer object which is transfered to the client, after editing the customer its send back to Grails and needs to be saved in the database. For performance I am not sending the complete customer object over the wire.
The problem is now if I want to store the customer object Grails validates of course the relationships of the customer object and fails. This is OK because I havent sent the relationsships.
My question is now how do I solve this problem now? Do I need to query the database again with the customer id and update the edited properties or is there a more elegant way? This looks a little bit expensive from database perspective as I need to read the database each time when storeing an object. As well from code perspective I need to check which properties are set and update them.
Thank you!
You cannot use save() for doing partial update, since grails cannot guess what fields you actually want to update: Maybe you REALLY want to set a field-value to NULL, so Grails cannot just ignore those fields. So I see two options:
Do it like you have described: Load the instance from DB, set the values and save again. You have mentioned, that you do not like to care what fields are updated, and you just want to take all attributes of your JSON instance. So assuming your already parsed JSON-instance is called jsonInstance and your database version of the customer is customerInstance, you can do:
jsonInstance.properties.each { field ->
customerInstance."${field.key}" = field.value
}
However, note that there are security limitations (if an attacker injects an 'id' attribute or other relevant attribute values into it, those will be just overwritten).
Use executeUpdate-function, see:
http://www.grails.org/doc/latest/ref/Domain%20Classes/executeUpdate.html
I think, if you really want to save performance, then go like this. However you have some hardcoded DML, which will cost maintainability and flexibility.
Related
Im trying to find out which attributes of an entity have been changed.
As far I have seen, there is a PersistenceSession with a method to check an object if an attribute isDirty. But its always true because it never registers the old object.
So if I take the demo from the QuickGuide and override the update method in the CoffeeBeanRepository:
/**
* #param \Acme\Demo\Domain\Model\CoffeeBean $coffeeBean
*/
public function update($coffeeBean) {
\TYPO3\Flow\var_dump($this->persistenceSession->isDirty($coffeeBean, 'name'), "name changed before");
parent::update($coffeeBean);
\TYPO3\Flow\var_dump($this->persistenceSession->isDirty($coffeeBean, 'name'), "name changed after");
}
... its always TRUE (both), despite I didn't change anything.
Anyone an idea/reference how this can be accomplished?
I am using it for a REST API where a user can't update several fields and on editing of some fields additional actions have to be executed.
The persistenceSession is part of the generic persistence backend of Flow and is neither maintained, nor really used unless you explicitly deactivate doctrine. Hence persistenceSession will not help you, because all entities are considered new for the persistenceSession as you noticed.
With doctrine you need to get the entity changeset from the "UnitOfWork", which you can get from an injected \Doctrine\Common\Persistence\ObjectManager. See also Is there a built-in way to get all of the changed/updated fields in a Doctrine 2 entity
However, this is a suboptimal solution and a hacky work-around at best. If you need to track changes to your entity, it should be an explicit part of your domain model. For example make your setters record a changed properties list, when the given value is different from the current.
When done, you could even optimize doctrines change tracking on the way with that: http://doctrine-orm.readthedocs.org/en/latest/reference/change-tracking-policies.html#notify
I have a scenario where I know the primary key of an entity (retrieved from an unrelated source), and I want to update just 1 property (db column). I have NOT already retrieved the entity from the database. If possible I would like to not have to make this extra round trip.
I create the entity using manager.createEntity.
I update one of the properties.
Then set the entityAspect to setModified();
When saving changes, all the properties that were not updated are set to their default values, and the generated SQL UPDATE statement attempts to update all mapped columns.
Is there a way to tell breeze to only generate SQL for specific properties/columns?
thanks
As you discovered, the properties of the originalValuesMap guide the Breeze server's ContextProvider as it prepares the save request. This is documented in the ContextProvider topic.
In your example, you call setModified after you've changed the property. All that does is change the EntityState; it doesn't create an entry in the client entity's entityAspect.originalValuesMap ... therefore the originalValuesMap sent to the server is empty.
I'm a little surprised that the EFContextProvider.SaveChanges prepared an EF update of the entire entity. I would have guessed that it simply ignored the entity all together. I'm making a mental note to investigate that myself. Not saying the behavior is "right" or "wrong".
You do not have to manipulate the originalValuesMap to achieve your goal. Just change the sequence. Try this:
var foo = manager.createEntity('Foo', {
id = targetId
}, breeze.EntityState.Unchanged); // create as if freshly queried
foo.bar = 'new value'; // also sets 'originalValues' and changes the EntityState
manager.saveChanges(); // etc.
Let us know if that does the trick.
Most of our tables have one or more columns which are set by the database, either by a trigger, or we want to use the database default value (which requires not sending the field at all in the insert or update)
This includes transaction dates set in the dB (so all the times are times stamped very accurately by a single source, not relying on the accuracy of the time on an arbitrary server or pc.)
The second VERY common use case is say if a customer record has his address and a last logged in field. the last logged in field (and number of failed logins) is set by another part of the system (e.g. by a web site server). The current overly simplistic CRUD system which GORM provides would overwrite such a field when an operator or customer edits their address for example. This is because GORM includes in its update and insert statements every field, even if it's null, or if it has not been changed.
We need a way to scrub the field from inserts and updates, but still have it used in the read calls.
I.e. a true "read only" attribute.
We tried this:
failedLogins editable: false, attributes: [readonly:true]
Which has no effect on the SQL generated (and doesn't even affect the scaffolded UIs - its still editable in create and edit, in grails 2.4.4 at least, but thats another story)
When we do want to explicitly write one of these fields, such as number of failed logins, we would resort to using embedded SQL.
I saw this post: Read-Only columns
Which asks exactly the same question, but only gives one solution, which is this plugin:
extended GORM mappings
Unfortunately, this plugin has not been updated since 2010, and only works with 1.3. We need something which works with 2.4.4.
Any grails app which has multiple systems which edits independent fields needs something like this, or to do extensive locking (Which is usually out of the question).
E.g. an operator opens the customer details for editing, edits something editable (e.g. address), then the operator fails a login on the website (a different grails or non-grails app), then the operator saves the player details. If the saving included the numberOfFailedLogins field, the system would fail. If opening the player details for editing locked the player, then the player would not be able to login, as updating the "lastLoggedIn" or "numFailedLogins" would fail to be able to write due to the lock. The solution is VERY simple - read only columns. Another way would be to put each read only type field in their own tables, but this would be untenable (and result in hundreds of one field tables)
Or we go back to using MyBatis, which has no such issues, and full control. Sadly, there is no good mybatis plugin for grails.
You can use derived properties for string and number properties:
class Batch {
String name
Integer timesRun
static mapping = {
timesRun formula: 'times_run' //times_run is a column in the "batch" table
}
}
In the code above, timesRun would be read in from the database but ignored in inserts and updates as Hibernate considers the column a calculated one.
Updated the example because the original one may have been misleading
This probably doesn't specifically answer your question, but you can use dynamicUpdates to tell GORM to only update the properties of the domain object that have changed during the current session. So as long as you don't change the "read-only" property in your code it won't be set in the SQL update statement generated by Grails. For added safety you could override (and noop) the setter so that your code can never change that property.
https://grails.github.io/grails-doc/latest/ref/Database%20Mapping/dynamicUpdate.html
One of the downsides of dynamicUpdates is that it might make the Hibernate query cache less useful. However, it seems that some Grails/Hibernate experts recommend that you disable the query cache anyway (at least in older versions of Grails). Not sure if that's true of Grails 2.4+
http://grails.github.io/grails-howtos/en/performanceTuning.html
http://www.anyware.co.uk/2005/2012/11/12/the-false-optimism-of-gorm-and-hibernate/
http://tech.puredanger.com/2009/07/10/hibernate-query-cache/
I have this problem of confusing when to include the entire object as a property of another object, or just its ID. It seems that if I include the entire object, the calls to load the containing object will unnecessarily also load the included object when I probably only need references. What is propert approach?
Generally always refer to another object.
Many ORM technologies have the idea of "proxies" and "lazy loading", meaning, unless you reference the object, it won't load it.
I prefer to include the object itself, since one object actually has a relationship with another actual object -- the object ID is just an implementation detail. To deal with the problem of unnecessary calls, look into "lazy loading".
Only include the other object if you need the details.
in MVC use a ViewModel ideally and not your entities. Your ViewModel contains only what it needs, so for example OrderEditViewModel would contain a customerid unless you want to display the custom name, in that case you would include the fields from customer. Some people recomend you flatten out your objects to a view model, so you dont have OrderEditViewModel.Customer.CustomerId but instead ORderEditViewModel.CustomerId. Automapper can help you do this (As well as valueinjecter - note the spelling)
If you must include an ID ensure when you save back to the database your update include a clause to say 'where id=#customerId and (logic here to ensure your user actually has access to that customerid and root object)
I have mvcsecurity.codeplex.com to help encrypt record ids on a web page to prevent against tampering as well (it helps but you should still have something in your query to prevent field tampering so an attacker cant add someone else's customer id for example_)
I go more into parameter tampering in MVC here if anyone is interested:
http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=hack-proofing-dotnet-app
My suggestion would be to always think about the design and not about performance. Performance can be tweaked but design can't. So, if the two objects have that kind of a relationship where Aggregation/Composition is required, you should do that.
But, if your containing object only has to deal with the ID (for e.g. passing it to a different object which processes the ID to do something) then you can keep the ID field only. No need to expose the whole object (but make sure that your containing object does not need to know anything about the other object.).
Here's my question:
I need to write a wizard, for customers to "create a new" very big objetc, with some other asociated with it: for example, Some images stored in another table (with relationships), some Lat's and Lang's for google earth, etc.
Each of them are stored in diferent tables in the Database, and that's why, i have to first insert to get the first object's Database generated ID to make the relationships with the another Objects. That's the reason I think puttin' Everything on just one View and hide selective DIVs with Jquery is not one of my option.
Session isn't an option because of the bigger object.
And because of the type of website, the wizard MUST be as follows:
Basic details of objetct 1
Images of object 1 (I will need here the ID of the first object)
Geolocations (with google maps, as before)
More details of object 1.
Preview
Publish
The point is, in step 4, user fill some fields that are required by the DB, and I cannot make them nullable as is it part of the customers reqs.
If somebody can a least give Ideas, will be nice...
Thanks in advance
You state that storing your object in Session is not desirable because of the size of the object. An alternative is to serialize that object and store it in the database. As the user progresses through the wizard, that object gets retrieved, updated and stored back in as a blob. Once they publish it, you can insert the appropriate records and remove the serialized object from whatever table you're storing them in.