Databinding
Data binding using MapBinder¶
Plugin comes with a MapBinder Which is used by a Repository to perform databinding. Plugin configures EntityMapBinder as default implementation of MapBinder. EntityMapBinder is similar to grails data binder in the sense that it uses registered value converters and fallbacks to spring ConversionService. However entityMapBinder is optimized to convert most commonly encountered property types such as Numbers and Dates without going through the converters, thus resulting in faster performance.
Example
class SomeService { @Autowired EntityMapBinder binder void foo(Map params) { Org org = new Org() binder.bind(org, params) } }
Using custom MapBinder
By default all Repositories use the default EntityMapBinder for databinding. However when a Repository is explicitly
created for a domain class, and if required, a custom MapBinder implementation can be used to perform databinding as per the need.
class CustomMapBinder implements MapBinder { public <T> GormEntity<T> bind(Map args, Object target, Map<String, Object> source, BindAction bindAction) { //implement } public <T> GormEntity<T> bind(Object target, Map<String, Object> source, BindAction bindAction) { //implement } }
beans = { customMapBinder(CustomMapBinder) }
class OrgRepo implements GormRepo<Org> { @Autowired @Qualifier("customMapBinder") CustomMapBinder mapBinder ......... }
This will make the OrgRepo use CustomMapBinder for data binding.
Binding Associations¶
Gorm tools MapBinder handles associations little differently than Grails data binder for performance reasons.
How associations are handled depends on if the associated domain belongs to the domain which is being bound.
If the domain being bound is owning side of association and value is of type map, a new instance of associated domain is created.
If the association does not use belongsTo then existing instance is loaded if the map contains the id.
The databinding on associated domain will be performed only if it belongs to the domain which is being bound
or the bindable:true
property is added to constraints for this association
Example
class Author { String name } class Category { String name } class Book { String name Category category static belongsTo = [author:Author] }
Given the above domain model, when creating a new book. It will not create new instance of Author or category, but will set reference to existing instance if id is provided in parameter. It will create new book and set the author and category to existing records with provided id.
Book.create([name:"Grails In Action", author:[id:1], category:[id:1]])
However a new book can be created when creating a new author, because book belongs to Author.
So following will create a new book instance and set author.book to this new instance.
Author.create(name:"test", book:[name:"Grails in action"])
It is possible to specify the bindable: true
property explicitly for the association in constraints of a parent domain class:
class Book { String name Category category static constraints = { category bindable:true } } class Category { String name }
category
contains bindable property and then binds category
to book
.
Otherwise, MapBinder consider the category
association as not bindable.