I am writing a web api using Spring and Postgres.
I have a case where I take a Json object item
The uri is /api/item/{itemId}
Request type is PUT
Json:
{
"name":"itemname",
"description":"item description here"
}
So I do (using JdbcTemplate) a SELECT statement to check if the itemId exists and then update if it does.
I would also like to implement a case with partial puts taking Json that look like this::
{
"name":"itemname"
}
OR
{
"description":"item description here"
}
where only the respective fields are updated. In Spring, the variables not present are automatically null.
The way this is implemented now is:
SELECT all columns from the items table
Sequentially check every single expected variable for null and if they are null, replace the null with the value selected from the table in step 1.
UPDATE all columns with the values (none of which should be null if the table has a not null constraint)
Question: How do you do this without == null or != null checks? Is seems to be poor design and involves iterating through every single expected variable for every single PUT request (I will have many of those).
Desired responses (in order of desirability):
There's a way in Postgres where if a null value is input, the column-value is simply not written to the database (and no error is produced)
There is a way to use Spring (and Jackson) to create a Java object with only the provided values and a way to generate SQL and JdbcTemplate code that only updates those specific columns.
Patch is the way of life - implement it
Change the front-end to always send everything
You have two choices when working with the database:
Just update what has changed, doing everything by yourself.
Get Jackson and Hibernate to do it for you.
So let's look at No. 1:
Let's say you're looking right now at the contents of an html form that has been sent back to the server. Take every field in the html form and update only those fields in the database using an SQL statement. Anything that is not in the form will not get updated in your database table. Simple! Works well. You don't need to worry about anything that is not in the form. You can restrict your update to the form's contents.
In general this is a simple option, apart from one problem, which is html checkboxes. If you are doing an update, html checkboxes can catch you out because due to a little design quirk, they don't get sent back to the server if they are unchecked.
No. 2: Perhaps you're looking for Hibernate, which you didn't mention. Jackson will fill a json object for you (must have a record id). Use Hibernate to populate a java class with the existing record, update with the new values Jackson has provided, then you tell Hibernate to merge() it into the existing record in the database, which it will. I also use Roo to create my Hibernate-ready classes for me.
No. 2 is hard to learn and set up, but once you've done sussed it, it's very easy to change things, add fields and so on.
Related
I am trying to get value like key and value pair but i am doing it from json file and now there is another approach suggested lets do it from db tables. because if in future value change then only update the DB is Needed.
I think using json file is more good as value hardly going to change in future(rarest of rare).. although advantage of db approach is just change the db value and done...
So My point is json will be faster then DB and Using Json will reduce load on DB..as clicking UI it invoke extra call of DB..
What do you Think .. Please let me know..
This very much depends on how you are going to use these data.
Do you need to update it often?
Do you need to update by just one specific field?
Do you need to fetch records based on some specific field?
Do you need to fetch whole json or just some specific fields?
Do some parts of json reference any other tables?
Also, consider the size of those data, e.g. if the json files together may become more in size than the whole other tables, you may break db cache. From the other hand, you can always create separate database for your json files if you still need some relational database features.
So, I would anyway start with answering first 5 questions.
I have a list of report types (objects) in the database that need to be generated for the user and sent out by email / printed / saved on hdd etc.
One report ('skeleton') is one row in database.
My question is: should I create a separate object for query result of one row - 'skeleton' report object and then use this object to create the end 'report' object. Is this the correct way of handling such task?
I have been told that it is easier to create a method and just get a rowset from the database in it. Then parse the row set for required parameters necessary to create the report, create the end report object and etc.
I am not totally sure if I understand your question correctly, but I assume that you want to know if you should fill an object with the data from the database and parse the object when creating the report or just pass the resultset to the creation method?
I would recommend using an object 'Skeleton' and filling this one, since you can reuse it later on and it makes the code way more readable in my opinion.
More information on this toppic:
In many applications the MVC pattern is used to structure your program. In this pattern you structure your program in 3 layers, the first one for your UI(VIEW), the second for you buisness logic(Controller) and the third one for your persistence data(Model). These layers only communicate through domain model objects which represent your data (in your case this would be the 'Skeleton' object, also called POJOs ). This is especially helpful if you suddenly want to change from a database to a textfile or any other persistence strategy, since you should only have to change the model layer while keeping the other layers mostly the same (especially if you're using interfaces). You can find a lot on this pattern in the internet and for most standard applications i would definitely recommend it
This is more complicated than the title makes it seem. Here's the problem:
I have a Spring Web Flow app which is a series of forms, which the user moves through in a specific order. Two forms, let's call them "Form 2" and "Form 3", populate different fields of the same database table, let's call it "Company." The trouble is, the Company table is all non-nullable fields. So when the user fills out the "Form 2" fields, and tries to save, the "Form 3" fields must be populated with something. For example, I have to save a foreign key value in the "Number of Employees" field.
Then, in the "Form 3", I have to read those fields back in and ignore the values that were just written, and present a blank form to the user. I would like to save a "sentinel" value in the FK field and detect it when it is re-read. However I am using Hibernate and I cannot determine the proper syntax to make Hibernate save what is essentially an "invalid" foreign key in this situation.
The table field I need to flag is this:
NUMBER_OF_EMPLOYEES CHAR(1) DEFAULT ' ' NOT NULL
The column is NOT NULL so I can't just put a NULL in it. The Hibernate/JPA relationship I need to put junk data in is this:
#ManyToOne(optional=true)
#JoinColumn(name = "NUMBER_OF_EMPLOYEES", nullable = true)
private NumberOfEmployees numberOfEmployees;
If the valid keys are, say, "A","B" and "C", I would like to put "X" in here. Is this possible, and if so, how?
Answer: You don't, at least without modifying the underlying table in the database since your DB server is going to enforce the not-null property even if Hibernate doesn't. Your best bet, absent the ability to use the information below, would be to pass an object around on the Session that gradually gets filled up with data.
However, since you mention you're using Spring, perhaps you can implement AbstractWizardFormController. That allows you to populate data as you go, and once the user finishes the last page you can commit all the data to the DB.
See the javadoc here:
http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/web/portlet/mvc/AbstractWizardFormController.html
and a tutorial here:
http://www.mkyong.com/spring-mvc/spring-mvc-handling-multipage-forms-with-abstractwizardformcontroller/
What about "-1", you can't abuse the system. Change your design or use it as you defined.
You can also remove the "not null" (sounds better to me than use "-1").
For persisting data used hibernate with SQLServer. In system every table contains four column.
1. Created User
2. Created Date
3. Modified User
4. Modified Date
From beginning system does not contain any mechanism for entering "modified User" and "modified Date" while insert and update operation.
My Question. is there any way in hibernate to entering modified User and Modified Date without changing every where ?
My question:
1)Is there any way to provide user(inform of Id or bean) to hibernate ?
2)If Yes,How can I tell to hibernate that populate this two columns while doing insert of records?
Thanks for any help.
One way would be to change of your servlets, or rest controllers, or possibly DAO's you are writing.
A second way is to create a DAO, servlet, or rest controller that gets the user object and date and make all of your servlets/daos/controllers extend the one you just made.
It is a pain in the behind but it would be better than setting a single point of context.
Passing security context(user) and date to a DAO is pretty easy to do and would be a lot easier to maintain in the future.
I have a program that pulls Salesforce Case objects, and their CaseComment and Solution objects. Also I have set of filters that allow me to reduce results (keywords, fromDate, toDate, etc.). The problem that I have is Salesforce functionality do not update neither Case LastModifiedDate nor SystemModstamp fields when I edit or create new comment for that Case.
The most straightforward solution to pull separately Cases, Comments and Solution then extract ParentId (CaseId) from Comments and Solutions, manually modify these CaseIDs with the max lastModifiedDate of Case or Solution and after that merge all Cases. But this process a bit routine, so I looking for another solution, both Salesforce and client sides.
If you want to avoid using Triggers you can use Workflow to do the 'touching'. As of the Spring '12 release of salesforce.com cross-object workflow is supported. So you can create a workflow rule on the case comment that updates a field on the parent case. You could create a custom field specifically for this touching process or reuse any other field.
For example to use the Case Description field as the touched field you could do the following.
Create a new workfow rule over the Case Comment object to fire whenever a record is created or edited.
Specify the criteria for the workflow rule to be when the created date is not equal to null.
Create a new workflow action for a field update.
Specify that the object should be Case and the Field Description
In the Formula enter Parent.Description as the value. This will set the Case Description to be its own value. Effectively making no change to the record.
With regards changing the LastModifiedDate or SysetemModstamp via the API I'm not sure that this is something you can do as part of an ongoing interface. Salesforce will allow you to update these audit fields via the API but you have to contact them to enable the functionality.
The salesforce online documentation covers the audit fields in more detail. It says:
If you import data into Salesforce and need to set the value for an audit field, contact salesforce.com. Once salesforce.com enables this capability for your organization, you can set audit field values for the following objects: Account, CampaignMember, Case, CaseComment, Contact, FeedComment, FeedItem, Idea, IdeaComment, Lead, Opportunity, and Vote. The only audit field you cannot set a value for is systemModstamp.
Simplest way I can think of is to just "touch" (update without making any modifications to the data) the Case record whenever a CaseComment is created or edited. This can be accomplished with a trigger on CaseComment:
trigger CaseCommentAIAU on CaseComment (after insert, after update) {
Set<Id> caseIds = new Set<Id>();
for ( CaseComment cc : Trigger.new ) {
caseIds.add(cc.ParentId);
}
Case[] caseUpdates = [select id from Case where Id in :caseIds];
update caseUpdates;
}