Something similar to Grails Domain properties field in Spring? - spring

I have started a new project in Spring Boot after using Grails for 4 years.
In Grails I have used properties field of an instance of a domain class to update the associate row in a db table. The assignment of domain.properties was usually done inside a service.
The properties field was set with data coming from a web form.
This approach allows to update a domain instance with a single line, instead of writing n assignemnt, where n is the number of the attributes defined in the domain class.
Now the question.. there is something similar in Spring?
I would like to do something similar in Spring:
update(Long radioId,Map properties) {
// get the radio to be update from the db
Radio radio = getRadio(radioId)
radio.properties = properties
save(radio)
}
I add some detail,
My controller
public ModelAndView updateRadio(Radio radio) {
radioService.update(radio);
return new ModelAndView("redirect:/superadmin/radio/"+radio.getIdentifier()+"/zoom");
}
My Service
#Service
public class RadioService {
...
public void update(Radio radio) {
assert radio.getId() != null;
radioRepository.save(radio);
}
...
}
Now if the web form does not explicity send all the fields defined in Radio I have problem since I will loose the value of the field already stored.
If I could write somthing like that
public void update(Map radioProperties,Long radioId) {
Radio radio = radioRepository.findById(radioId);
radio.properties = radioProperties // only properties present in this map will be update (in grails)
radioRepository.save(radio);
}
it would be great.
In the latter method only the properties in the map (ence in the web form) will be updated, and the other store field of the radio instance will be untouched.

Take a look at Spring Data JPA, it can load domain objects by id, bind incoming request parameters to domain objects and also automagic you some CRUD repositories.

Related

How to decide a type of GetMapping method in Spring boot?

I'm spring boot learner and trying to clone-code a website. Below is a code to get a data of the specific content.
#GetMapping("/api/articles/{id}")
public List<Article> takeArticle() { return articleRepository.findAllByOrderByModifiedAtDesc();}
Then the ARC shows whole data of contents which I've already posted, but I want a specific data according to the id value. I think the problem is the type of takeArticle() method. So which type should be used for the method above to fulfill my purpose?
#GetMapping("/api/articles/{id}")
public Article takeArticle(#PathVariable Integer id) {
return articleRepository.findById(id).orElseThrow(() -> {
// throw Not found exception if article doesn't exists with given id
});
}
By the way you shouldn't use repository interfaces directly in your controller layer. Use service layer between repository and controllers.

Spring Data JPA and Spring Web Updating Entities Avoiding Associations

I have the following entities:
Area
Listing
They are both many-to-many:
An area can have many listings
A listing can have many areas
Both Area and Listing have other fields like name, domain, etc.
I'm using Spring Web RestController as a way to update the entities.
For example:
#PutMapping("/{id}")
public Area update(#PathVariable Long id, #RequestBody Area update) {
return areaRepository.save(update);
}
However, as an Area can have many thousands of Listings, it's not practical to pass them all in the update request when I just want to update the Area name and other basic fields in my web application.
For example, the update json in the http request would be:
{
"id" : 69,
"name" : "San Francisco",
"domain" : "foo",
...
}
When serialised, the area instance above will have a listings field equal to null (obviously) and then when saved, all association are remove from this Area.
I'm thinking that I could do a select-then-update set of operations and only update the values necessary but that is cumbersome - especially when there are many dozens of non-association fields.
The question would be: how can I try to keep to the above code and http request and not remove all of the existing Listing associations when saving the input area? Is this possible? I want to update the name and other basic fields but not the association fields.
You can use the BeanUtilBean(org.apache.commons.beanutils.BeanUtilsBean).
Step 1: Create custom beanutilbean class.
#Component
public class CustomBeanUtilsBean extends BeanUtilsBean {
#Override
public void copyProperty(Object dest, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if(value==null)return;
super.copyProperty(dest, name, value);
}
}
Step 2: In your controller while updating. first get the Area from database & use copyProperties method as shown in below.
#PutMapping("/{id}")
public Area update(#PathVariable Long id, #RequestBody Area update) {
Area areaDB = areaRepository.findOne(update.getId());
customBeanUtilsBean.copyProperties(areaDB,update);//it will set not null field values of update to areaDB.
return areaRepository.save(areaDB);
}
Hope this will helps you..:)
Since you are using spring-data-jpa repository you can write a new method that takes the changed values of Area object with #Modifying and #Query annotations on it.
In the #Query you specify the HQL query with update statement as in here

Spring boot + JPA(Hibernate) Edit partial entity fields

all.
I have following simple form in which I want to edit the entity. The problem is that I have some fields which I don't want to be edited. For example (Image file path).
As it is now, I have the service method -
public void addOrModifyLayout(Layout layout){
if(layout.getId() == null){
layoutRepository.save(layout);
}
else {
Layout modifiedLayout = new Layout();
modifiedLayout.setId(layout.getId());
modifiedLayout.setName(layout.getName());
modifiedLayout.setStatus(layout.getStatus());
modifiedLayout.setExhibitor(layout.getExhibitor());
layoutRepository.save(modifiedLayout);
}
}
As you can see, every field that I want to be able to be edited, I should explicitly put it in the service. Can I use some mapper or trick to update only some fields that are in the view (form) ? How you handle this kind of issues?
You can either
store all the entity fields in hidden inputs (e.g. imageFilePath hidden input). So you can store on UI all the entity fields and get them back to assign to the entity.
OR
Avoid new entity creation but retrieve existing one and fill only necessary fields.
Layout modifiedLayout = layoutRepository.getById(layout.getId());
modifiedLayout.setName(layout.getName());
modifiedLayout.setStatus(layout.getStatus());
modifiedLayout.setExhibitor(layout.getExhibitor());
layoutRepository.save(modifiedLayout);

Setup knockoutJS view model to bind to one-to-many property

I have a controller in grails that I am sending an ajax JSON post to with a knockoutJS view model. The view model (along with a javascript object) looks like this:
var childProperty= function(name, id) {
this.name = name;
this.id = id;
};
//KnockoutJS - Main view model
var viewModel = {
id: ko.observable(1),
childProperty: ko.observable(new childProperty("Chuck",1))
}
The data model on the controller side is trying to automatically use the Spring binding magic and bind the JSON request parameters to a new instance of my data model like so:
def jUpdate = {
def update = new SomeObject(params)
}
The problem comes in when I want the Spring binding to detect that childProperty.id is a one-to-many relationship in the data model and to go fetch the related property in the data model. The Grails documentation says this:
Data binding and Associations
If you have a one-to-one or many-to-one association you can use
Grails' data binding capability to update these relationships too. For
example if you have an incoming request such as:
/book/save?author.id=20
Grails will automatically detect the .id
suffix on the request parameter and look-up the Author instance for
the given id when doing data binding such as:
def b = new Book(params)
I am using the ko.toJS utility function and the simple properties are binding correctly. How can I set the view model child property up so that when it is posted to the grails controller, Spring detects it properly and fetches the associated record and builds the object?
I was never able to get the automagic spring bindings to work, so I just passed over the id for the child objects and manually set them on the server side in the params map. After that, GORM fetches the record appropriately. Something like this:
def update = {
params.put("childObject.id",params.childObjectId)
params.remove("childObjectId")
def parentObject = new ParentObject(params)
}
This fetches the related items and builds the object. If you had a lot of related fields, this would become a painful process.

In Spring MVC 3, how do I bind an object to a query string when the query string parameters don't match up with the object fields?

A 3rd party is sending me part of the data to fill in my domain object via a query string. I need to partially fill in my domain object, and then have the user fill in the rest via a form. I don't have any control over the query string parameters coming in, so I can't change those, but I'd really like to be able to use Spring MVC's data binding abilities, rather than doing it by hand.
How can I do this?
To add some complication to this, some of the parameters will require extensive processing because they map to other objects (such as mapping to a user from just a name) that may not even exist yet and will need to be created. This aspect, I assume, can be handled using property editors. If I run into trouble with this, I will ask another question.
Once I have a partially filled domain object, passing it on to the edit view, etc. is no problem, but I don't know how to properly deal with the initial domain object population.
The only thing I have been able to come up with so far is to have an extra class that has it's properties named to match the inbound query parameters and a function to convert from this intermediary class to my domain class.
This seems like a lot of overhead though just to map between variable names.
Can you not just have the getter named differently from the setter, or have 2 getters and 2 setters if necessary?
private int spn;
// Standard getter/setter
public int getSpn() {
return spn;
}
public void setSpn(int spn) {
this.spn = spn;
}
// More descriptively named getter/setter
public int getShortParameterName() {
return spn;
}
public void setShortParameterName(int spn) {
this.spn = spn;
}
Maybe that is not standard bean convention, but surely would work?

Resources