Update only "changed values" for an existing entity - spring

I am creating a rest API to update my entity with the new changes, but my entity is having like 20 attributs and i don't think it's a good way to just put multiple sets and "if" conditions to not set old values with NULL.
I want to know if there is a way in spring that can update the whole entity without changing the old unchanged values to null instead of putting a lot of Setters (~20 in my case).

Related

Change length of name fields

We are using Dynamics CRM 2016 on-premise. When you create a custom entity, you get a default "name" field which is a string with 100 characters. You can change that datatype during entity creation but we didn't do that.
Now we learned that 100 chars are not enough in our usecase, we would need 120 or 150.
The solution designer allows changing the string length but when we save the changes we get a generic database error.
Question: Is there a known workaround to change the string length of the main field?
Obviously, it is possible to create a new entity and copy the data from the old to the new entity. Since we have many views, forms and references between entities, this is not really feasible.
This is not possible using any conventional solutions (i.e. through the UI) due to constraints in the Database. The default name field is the primary key of the table. I encourage you to remake the entity and migrate existing data to the new entity.
If this is really not feasible then you can try to change the length of the column directly in the SQL DB, but that is unsupported so it might break the environment. If you want to try this be sure that you test this in an disposable environment.
I have never done it so I don't know the outcome but that is something that I would try.

how can i update an object/entity that is not completely filled out?

I have an entity with several fields, but on one view i want to only edit one of the fields. for example... I have a user entity, user has, id, name, address, username, pwd, and so on. on one of the views i want to be able to change the pwd(and only the pwd). so the view only knows of the id and sends the pwd. I want to update my entity without loading the rest of the fields(there are many many more) and changing the one pwd field and then saving them ALL back to the database. has anyone tried this. or know where i can look. all help is greatly appreciated.
Thx in advance.
PS
i should have given more detail. im using hibernate, roo is creating my entities. I agree that each view should have its own entity, problem is, im only building controllers, everything was done before. we were finders from the service layer, but we wanted to use some other finders, they seemed to not be accessible through the service layer, the decision was made to blow away the service layer and just interact with the entities directly (through the finders), the UserService.update(user) is no longer an option. i have recently found a User.persist() and a User.merge(), does the merge update all the fields on the object or only the ones that are not null, or if i want one to now be null how would it know the difference?
Which technologies except Spring are you using?
First of all have separate DTOs for every view, stripped only to what's needed. One DTO for id+password, another for address data, etc. Remember that DTOs can inherit from each other, so you can avoid duplication. And never pass business/ORM entities directly to view. It is too risky, leaks in some frameworks might allow users to modify fields which you haven't intended.
After the DTO comes back from the view (most web frameworks work like this) simply load the whole entity and fill only the fields that are present in the DTO.
But it seems like it's the persistence that is troubling you. Assuming you are using Hibernate, you can take advantage of dynamic-update setting:
dynamic-update (optional - defaults to false): specifies that UPDATE SQL should be generated at runtime and can contain only those columns whose values have changed.
In this case you are still loading the whole entity into memory, but Hibernate will generate as small UPDATE as possible, including only modified (dirty) fields.
Another approach is to have separate entities for each use-case/view. So you'll have an entity with only id and password, entity with only address data, etc. All of them are mapped to the same table, but to different subset of columns. This easily becomes a mess and should be treated as a last resort.
See the hibernate reference here
For persist()
persist() makes a transient instance persistent. However, it does not guarantee that the
identifier value will be assigned to the persistent instance immediately, the assignment
might happen at flush time. persist() also guarantees that it will not execute an INSERT
statement if it is called outside of transaction boundaries. This is useful in long-running
conversations with an extended Session/persistence context.
For merge
if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
the persistent instance is returned
the given instance does not become associated with the session, it remains detached
persist() and merge() has nothing to do with the fact that the columns are modified or not .Use dynamic-update as #Tomasz Nurkiewicz has suggested for saving only the modified columns .Use dynamic-insert for inserting not null columns .
Some JPA providers such as EclipseLink support fetch groups. So you can load a partial instance and update it.
See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/AttributeGroup

Autonumbering in new entity

I have an custom entity which needs to have a case number for an XRM Application, can I generate a case number from the Service -> Case.
If this is not possible, how can I do this with a plugin, I've looked at the crmnumbering.codeplex.com but this doesn't support 2011, anybody outthere have a solution or should I rewrite it myself?
thanks
I've ran into this same type of issue (I need a custom # for an entity). Here's how you can do it:
Create an Entity called "Counter"
Add a field called "new_customnumber", make it a string or a number depending on what you want
Create a new record for that entity with whatever you want in the new_customnumber field (let's say "10000")
Create a plugin (EntityNumberGenerator) that goes out and grabs that record (you'll probably want to set the security on this record/entity really tight so no one can mess with the numbers)
On Create of the "custom entity" fire the plugin. Grab the value in new_customnumber save it to the "custom entity" (let's say in a "case" field) increment the new_customnumber and save it to the Counter entity.
Warning, I'm not sure how this is with concurrency. Meaning I'm not sure if 2 custom entities being created at the same time can grab the same number (I haven't ran into an issue yet). I haven't figured out a way to "lock" a field I've retrieved in a plugin (I'm not sure it's possible).
You will be unable to create a custom number for custom entities from the normal area you set a case number.
Look at the CRM2011sdk\sdk\samplecode\cs\plug-ins\accountnumberplugin.cs plugin. It's really similar to what you want.
Ry
I haven't seen one for 2011 yet. Probably easiest to write it yourself.
I've always created a database with a table with a single column which is an IDENTITY column. Write an SP to insert, save the IDENTITY value to a variable, and DELETE the row all within a transaction. Return the variable. Makes for a quick and easy plug-in and this takes care of any concurrency issues.
The performance is fast and the impact to your SQL server is minimal.

Using Linq SubmitChanges without TimeStamp and StoredProcedures the same time

I am using Sql tables without rowversion or timestamp. However, I need to use Linq to update certain values in the table. Since Linq cannot know which values to update, I am using a second DataContext to retrieve the current object from database and use both the database and the actual object as Input for the Attach method like so:
Public Sub SaveCustomer(ByVal cust As Customer)
Using dc As New AppDataContext()
If (cust.Id > 0) Then
Dim tempCust As Customer = Nothing
Using dc2 As New AppDataContext()
tempCust = dc2.Customers.Single(Function(c) c.Id = cust.Id)
End Using
dc.Customers.Attach(cust, tempCust)
Else
dc.Customers.InsertOnSubmit(cust)
End If
dc.SubmitChanges()
End Using
End Sub
While this does work, I have a problem though: I am also using StoredProcedures to update some fields of Customer at certain times. Now imagine the following workflow:
Get customer from database
Set a customer field to a new value
Use a stored procedure to update another customer field
Call SaveCustomer
What happens now, is, that the SaveCustomer method retrieves the current object from the database which does not contain the value set in code, but DOES contain the value set by the stored procedure. When attaching this with the actual object and then submit, it will update the value set in code also in the database and ... tadaaaa... set the other one to NULL, since the actual object does not contain the changed made by the stored procedure.
Was that understandable?
Is there any best practice to solve this problem?
If you make changes behind the back of the ORM, and don't use concurrency checking - then you are going to have problems. You don't show what you did in step "3", but IMO you should update the object model to reflect these changes, perhaps using OUTPUT TSQL paramaters. Or; stick to object-oriented.
Of course, doing anything without concurrency checking is a good way to lose data - so my preferred option is simply "add a rowversion". Otherwise, you could perhaps read the updated object out and merge things... somehow guessing what the right data is...
If you're going to disconnect your object from one context and use another one for the update, you need to either retain the original object, use a row version, or implement some sort of hashing routine in your database and retain the hash as part of your object. Of these, I highly recommend the Rowversion option as well. Using the current value as the original value like you are trying to do is only asking for concurrency problems.

Linq-to-SQL How to prevent the use of Delete methods?

By convention our DB only alows the use of stored procedures for INSERT, UPDATE and DELETE. For some tables / types there is no DELETE stored procedure, because it is not allowed to delete rows. (You can only update the status of such a type to "deleted"). e.g. a customer may be marked as deleted but is never really removed from the DB.
How do I prevent the use of Delete() for certain types in the Data Access Layer = in the DMBL?
The "Default Methods" for Insert and Update are mapped to the corresponding stored procedure. But for Delete it says "use runtime". I would like to set it to "not allowed".
Is there a way to achieve this on the DB model layer?
Many thanks
Implement a partial class for each such entity and implement the OnValidate partial method. It takes a ChangeAction as a parameter. When the ChangeAction is ChangeAction.Delete, throw an exception that indicates that the operation is disallowed (IllegalOperationException, maybe).
I had the same constraint while developing one of my application. You can always condifure the delete action to use a certain stored procedure instead of the framework generating a sql command for the same. In my case when I say delete we just wanted to mark a particular row as deleted but not physically deleting it. So our update stored procedure was reused in the delete command to simply mark the isDeleted col value as true. Besides that you may want to build some kind of wrapper around the classes built by DBML and suppress the delete methods. Right now I do not see any speciall setting to have the framework only generate create and update methods. Partial classes may be one more alternative.
How about to configure rights for the user you're using to connect to DB? You can set Deny for Delete operation for this particular user, so it wouldn't be possible to use DELETE statement on DB level.
The deletion API is not generated, by which I mean an option on a generated table cannot remove the ability to mark an item as deleted. DeleteOnSubmit is part of the Table<TEntity> class.
If it is always an error to delete an entity, OnValidate should throw an InvalidOperationException as tvanfosson suggests.
I tried mapping Linq to Sql deletes to stored procedures which simply set the field to true. It gets weird because the DataContext removes instances after "deleting", but they are legal domain entities and should still be in the DataContext after submitting.

Resources