有关于Association和Collection的探究
场景:一个父亲有多个儿子,一个儿子只有一个父亲(一对多场景)
数据库表结构:
father表:fid(int unique),fname(varchar)
son表:sid(int unique),sname(varchar),s_fid(int)
father表中的fid是主键
son表中的s_fid是father表中fid的外键
pojo:
Father类:fid(int),fname(String),slist(List<Son>)
Son类:sid(int),sname(String),f(Father)
Father中加入List用于保存对应的多个儿子
Son中加入一个Father对象来保存唯一的父亲
mapper:
FatherMapper:由于是含有多个儿子,利用collection对应slist
<resultMap type="father" id="fatherMap"> <!-- id=代表主键映射 property=javaBean中的属性 column=数据库中的字段 --> <id property="fid" column="fid" /> <!-- 非主键映射 --> <result property="fname" column="fname" /> <collection property="slist" ofType="Son" javaType="ArrayList" column="s_fid"> <id property="sid" column="sid"/> <result property="sname" column="sname"/> </collection> </resultMap>
SonMapper:由于含有唯一的爸爸,利用association对应Father
<resultMap type="son" id="sonMap"> <!-- id=代表主键映射 property=javaBean中的属性 column=数据库中的字段 --> <id property="sid" column="sid" /> <!-- 非主键映射 --> <result property="sname" column="sname" /> <association property="f" column="s_fid" javaType="father"> <id property="fid" column="fid"/> <result property="fname" column="fname"/> </association>
</resultMap>
可以看到数据库里的字段和pojo类里的字段其实是不匹配的
而且我们给父亲加了一个儿子列表,给儿子加了一个父亲对象,但是SQL的数据类型没有对象和列表,这个时候如何利用SQL语句进行赋值呢?
于是collection和association的功能就体现出来了
我们把代码中的collection和association抠出来,其实里面包的就是我们的java类型
对象里的基本数据类型,用这种形式可以做到利用sql访问
下面给出FatherMapper里选择儿子的DQL和SonMapper里选择爸爸的DQL:
<select id="getSons" parameterType="father" resultMap="fatherMap"> SELECT father.fid,father.fname,son.sid,son.sname from father join son where father.fid=son.s_fid </select>
<select id="getFather" resultMap="sonMap"> SELECT son.sid,son.sname,son.s_fid,father.fname,father.fid from son join father where son.sid=#{sid} and father.fid=son.s_fid </select>
查找出来的字段,只要映射map里有,就填进去
儿子找爸爸的DQL中其实做了5件事,给5个成员变量做了setter:给儿子的sid,sname,s_fid执行setter,再给Father成员变量内的fname和fid执行setter
爸爸找儿子的DQL同理
我们使用了association和collection,相当于点操作,father.set( )。而它的真正意义是映射,把字段映射出来,使sql语句可以对其操作
总结:处理一对多的问题时,设计pojo要给双方都多加一个字段,用于保存对应记录,这样的处理方式使我们的映射文件非常优雅简洁。