mapping - Grails GORM default sort field which is also a field of a composite key -
my grails version 2.5.0
i have 2 domain classes:
import org.apache.commons.lang.builder.hashcodebuilder class templateheader implements serializable { int headerid int ver string templatename string extradescription string servicetype string createdby boolean isactive string updatedby date datecreated date lastupdated static hasmany = [templateitems: templateitem] static mapping = { id composite: ['headerid', 'ver'] ver comment:'' templatename length: 40 servicetype length: 20 extradescription length: 60 isactive defaultvalue:false templateitems sort:'itemno', order:'asc' } static constraints = { headerid unique: 'ver' templatename nullable: false servicetype nullable: false } boolean equals(other) { if (!(other instanceof templateitem)) { return false } other.id == id && other.ver == ver } int hashcode() { def builder = new hashcodebuilder() builder.append id builder.append ver builder.tohashcode() } }
=======================================================
import org.apache.commons.lang.builder.hashcodebuilder class templateitem implements serializable { int itemno string itemname; string unitname; int unitprice; double defaultvalue boolean allowchange string extracomment string createdby string updatedby date datecreated date lastupdated static belongsto = [templateheader:templateheader] static mapping = { id composite: [ 'templateheader', 'itemno'] itemno comment:'' itemname length: 60 unitname length: 4 unitprice comment:'' extracomment length: 60 defaultvalue comment:'' allowchange comment:'' } static constraints = { itemname nullable: false unitname nullable: false extracomment nullable: true defaultvalue nullable: false } boolean equals(other) { if (!(other instanceof templateitem)) { return false } other.itemno == itemno && other.templateheaderid == templateheaderid } int hashcode() { def builder = new hashcodebuilder() builder.append templateheaderid builder.append itemno builder.tohashcode() } }
when run grails application, shows below exception when build tables:
|running grails application context.grailscontextloaderlistener error initializing application: error creating bean name 'transactionmanagerpostprocessor': initialization of bean failed; nested exception org.springframework.beans.factory.beancreationexception: error creating bean name 'transactionmanager': cannot resolve reference bean 'sessionfactory' while setting bean property 'sessionfactory'; nested exception org.springframework.beans.factory.beancreationexception: error creating bean name 'sessionfactory': invocation of init method failed; nested exception org.codehaus.groovy.grails.exceptions.grailsdomainexception: property sort clause not found: accudata_portal.templateitem.itemno org.springframework.beans.factory.beancreationexception: error creating bean name 'transactionmanagerpostprocessor': initialization of bean failed; nested exception org.springframework.beans.factory.beancreationexception: error creating bean name 'transactionmanager': cannot resolve reference bean 'sessionfactory' while setting bean property 'sessionfactory'; nested exception org.springframework.beans.factory.beancreationexception: error creating bean name 'sessionfactory': invocation of init method failed; nested exception org.codehaus.groovy.grails.exceptions.grailsdomainexception: property sort clause not found: accudata_portal.templateitem.itemno @ java.util.concurrent.futuretask.run(futuretask.java:262) @ java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1145) @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:615) @ java.lang.thread.run(thread.java:745) caused by: org.springframework.beans.factory.beancreationexception: error creating bean name 'transactionmanager': cannot resolve reference bean 'sessionfactory' while setting bean property 'sessionfactory'; nested exception org.springframework.beans.factory.beancreationexception: error creating bean name 'sessionfactory': invocation of init method failed; nested exception org.codehaus.groovy.grails.exceptions.grailsdomainexception: property sort clause not found: accudata_portal.templateitem.itemno ... 4 more caused by: org.springframework.beans.factory.beancreationexception: error creating bean name 'sessionfactory': invocation of init method failed; nested exception org.codehaus.groovy.grails.exceptions.grailsdomainexception: property sort clause not found: accudata_portal.templateitem.itemno ... 4 more caused by: org.codehaus.groovy.grails.exceptions.grailsdomainexception: property sort clause not found: accudata_portal.templateitem.itemno ... 4 more error | forked grails vm exited error
does tell me how fix ? thank you
i wonder why your'e not getting errors fields using in mapping closure , have not defined mappings itemno, unitprice, defaultvalue etc.
also equals condition in temapletheader domain should be:
if (!(other instanceof templateheader))
now comming question, getting error because itemno property inside templateitem domain not in templateheader domain. sort keyword accepts map.
to sort templateitem objects based on itemno field, have define sort property in mapping closure templateitem domain
static mapping = { . . . sort 'itemno': 'asc' }
now whenever make query templateitem, default sorting on itemno field. if use
templateitem.findallbytemplateheader(templateheaderinstance)
it give sorted templateitems based on itemno.
by defining sort property in templateitem domain not sort templateitems field in templateheader domain. reason while fetching association domain object grails ignores sort field domain. if @ sql being generated while fetching templateheader object , associations see difference.
apparently there no direct way want achieve, depending upon whether want sort temapleheader objects based on templateitems or sort templateitems within single templateheader object
to sort templateheader objects based on templateitems, add below sort property mapping closure of templateheader domain:
static mapping = { . . . sort 'templateitems.itemno': 'asc' }
and when execute gorm
templateheader header = templateheader.list()
it generates following sql
select this_.header_id header_i1_0_1_, this_.ver ver2_0_1_, .... template_header this_ inner join template_item templateit1_ on this_.header_id=templateit1_.template_header_header_id , this_.ver=templateit1_.template_header_ver order templateit1_.item_no asc
now problem query execution cost high. using inner join between templateheader , templateitem domains. if have 2 records in templateheader domain , 10 in templateitem domain, fetch 10 record while need 2. issue templateitems property still fetched lazily. while header.templateitems, again make query database , result not sorted based on itemno. sql this:
select templateit0_.template_header_header_id template1_0_0_, templateit0_.template_header_ver template2_0_0_, ... template_item templateit0_ templateit0_.template_header_header_id=? , templateit0_.template_header_ver=?
so if want sort templateitems templateheader object, can on ride getter templateitems , sort result there:
set<templateitem> gettemplateitems() { return templateitems?.sort { item_1, item_2 -> item_1?.itemno <=> item_2?.itemno } }
just in case if error while adding templateitem object templateheader object:
no signature of method: templateheader.addtotemplateitems() applicable argument types: (templateitem)
then try declaring templateitems list.
Comments
Post a Comment