java - MyBatis ManyToOne & OneToMany mapping -
i use java 7 , mybatis 3.2.2. problem following. have 3 classes - a, b, c.
a has list of b, b has list of c. - 1 many
c has set b, b has set a. - many one
/* * java classes */ public class { private int id; private list<b> blist; ... } public class b { private int id; private a; private list<c> clist; ... } public class c { private int id; private b b; ... } /* * mybatis result maps */ <resultmap id="amap" type="a"> <id property="id" column="a_id" /> <collection property="list" column="b_id" oftype="b" resultmap="bmap"/> </resultmap> <resultmap id="bmap" type="b"> <id property="id" column="b_id" /> <association property="a" column="a_id" resultmap="amap"/> <collection property="list" column="c_id" oftype="c" resultmap="cmap"/> </resultmap> <resultmap id="cmap" type="c"> <id property="id" column="c_id" /> <association property="b" column="b_id" resultmap="bmap"/> </resultmap> /* * mybatis select */ <select id="get..." resultmap="xmap"> select a.id a_id, b.id b_id, c.id c_id a left join b b on a.id = b.ida left join c c on b.id = c.idb </select>
/* * problem */
when resultmap xmap = amap correct. objects created , populate properly
when resultmap xmap = cmap error bellow thrown.
when amap removed collection of bs - correct. - wierd, looks mybatis can map depth??
this issue complicates work in sense of reusability of mybatis elements. off course can create result maps broke reusability principles.
any idea how solve this?
/* * error - mybatis throws following exception: */
org.mybatis.spring.mybatissystemexception: nested exception org.apache.ibatis.reflection.reflectionexception: not set property 'blist' of 'a' value 'b [id=1]' cause: java.lang.illegalargumentexception: argument type mismatch @ org.mybatis.spring.mybatisexceptiontranslator.translateexceptionifpossible(mybatisexceptiontranslator.java:73) @ org.mybatis.spring.sqlsessiontemplate$sqlsessioninterceptor.invoke(sqlsessiontemplate.java:364) @ com.sun.proxy.$proxy23.selectlist(unknown source) @ org.mybatis.spring.sqlsessiontemplate.selectlist(sqlsessiontemplate.java:194) @ org.apache.ibatis.binding.mappermethod.executeformany(mappermethod.java:114) @ org.apache.ibatis.binding.mappermethod.execute(mappermethod.java:58) @ org.apache.ibatis.binding.mapperproxy.invoke(mapperproxy.java:43) @ com.sun.proxy.$proxy45.getkeywordsbynoderesult(unknown source) @ xtest.testgetkeywordsbynoderesult(workflowmappertest.java:35) @ sun.reflect.nativemethodaccessorimpl.invoke0(native method) @ sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl.java:62) @ sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:43) @ java.lang.reflect.method.invoke(method.java:498) @ org.junit.runners.model.frameworkmethod$1.runreflectivecall(frameworkmethod.java:47) @ org.junit.internal.runners.model.reflectivecallable.run(reflectivecallable.java:12) @ org.junit.runners.model.frameworkmethod.invokeexplosively(frameworkmethod.java:44) @ org.junit.internal.runners.statements.invokemethod.evaluate(invokemethod.java:17) @ org.springframework.test.context.junit4.statements.runbeforetestmethodcallbacks.evaluate(runbeforetestmethodcallbacks.java:72) @ org.springframework.test.context.junit4.statements.runaftertestmethodcallbacks.evaluate(runaftertestmethodcallbacks.java:81) @ org.springframework.test.context.junit4.statements.springrepeat.evaluate(springrepeat.java:72) @ org.junit.runners.parentrunner.runleaf(parentrunner.java:271) @ org.springframework.test.context.junit4.springjunit4classrunner.runchild(springjunit4classrunner.java:216) @ org.springframework.test.context.junit4.springjunit4classrunner.runchild(springjunit4classrunner.java:82) @ org.junit.runners.parentrunner$3.run(parentrunner.java:238) @ org.junit.runners.parentrunner$1.schedule(parentrunner.java:63) @ org.junit.runners.parentrunner.runchildren(parentrunner.java:236) @ org.junit.runners.parentrunner.access$000(parentrunner.java:53) @ org.junit.runners.parentrunner$2.evaluate(parentrunner.java:229) @ org.springframework.test.context.junit4.statements.runbeforetestclasscallbacks.evaluate(runbeforetestclasscallbacks.java:60) @ org.springframework.test.context.junit4.statements.runaftertestclasscallbacks.evaluate(runaftertestclasscallbacks.java:67) @ org.junit.runners.parentrunner.run(parentrunner.java:309) @ org.springframework.test.context.junit4.springjunit4classrunner.run(springjunit4classrunner.java:162) @ org.eclipse.jdt.internal.junit4.runner.junit4testreference.run(junit4testreference.java:86) @ org.eclipse.jdt.internal.junit.runner.testexecution.run(testexecution.java:38) @ org.eclipse.jdt.internal.junit.runner.remotetestrunner.runtests(remotetestrunner.java:459) @ org.eclipse.jdt.internal.junit.runner.remotetestrunner.runtests(remotetestrunner.java:675) @ org.eclipse.jdt.internal.junit.runner.remotetestrunner.run(remotetestrunner.java:382) @ org.eclipse.jdt.internal.junit.runner.remotetestrunner.main(remotetestrunner.java:192)
.....
you don´t need mybatis this. can define list of childs parent tracking way:
public abstract class listwithparenttracking<child> extends arraylist<child> { @override public boolean add(child c) { this.setparent(c); return super.add(c); } protected abstract void trackparent(child c); };
then define class as:
public class { private int id; private final list<b> blist; ... public a() { final me = this; this.blist = new listwithparenttracking<b>() { @override protected void trackparent(b b) { b.seta(me); } } } }
and let own objects magic.
Comments
Post a Comment