mybatis关联映射

JAVA ginotang 806℃ 0评论

关联映射

关联映射是用来描述数据库中多个表的关系的,通常有一对一、一对多、多对多的关系。其中多对多的关系最为复杂,实际生产环境中最好对这种关系进行简化或拆解,因此本文不涉及多对多关系。

mybatis中的关联映射通过元素<association>、<collection>处理,这些元素都定义在<resultMap>中。关联映射关系在javaBean中通常表现为has-a(有一个)的关系。例如一对一关系,一个公民对应一个身份证,在JavaBean的关系表现为:

 

一对一关联

一对一关联是最简单的数据库关系,例如一个公民对应一个身份证。一对一关系使用<association>处理。测试之前先建立两张表,一张user表,一张id_card表,id_card用来保存完整的身份证信息。id_card的user_id对应user中的id。关系如下:

association

编写UserMapper.xml配置文件:

第一个resultMap中的association是关系配置的核心,它指定了User对象对应的另一个关系(idCard)。我们分析一下它的三个属性代表什么:

  • property=”idCard” :       一个User对应一个idCard
  • select=”findIdCardByUserId”:使用findIdCardByUserId定义的sql查询IdCard对象
  • column=”id”:此属性作为findIdCardByUserId的参数传递过去,也就是传递给sql语句中的#{user_id}

编写测试方法

代码中的User和IdCard已经预先编写好,篇幅所限,这里不再列出。selectUser方法也已经在UserMapper接口中定义。

一对多关联

例如一个班级中有多名学生,一个顾客多个订单,一个员工可以有多个职务等等,这些都是一对多的关系。一对多中的多实际上使用集合来表示非常合适,mybatis也正是这么做的。

以员工和职务之间的关系作为例子,一个员工既可以是CEO,也可以是CTO。这种关系通常都需要第三张表来维护,以避免数据库冗余的产生。

建立表结构

分别建立三张表:员工表(staff)、职务表(title)、关系维护表(staff_title)。

其中关系维护表中保存员工表中的id和职务表的id。


database relation

插入测试内容

测试数据关系:Jack既是CEO也是CTO, Tom既是COO也是CFO。

数据库内容如下:

data

编写StaffMapper配置文件

可以通过两种方式实现一对多的关系,其中一种方法基本上和一对一配置一样,只是使用collection代替association。

一对多关联中的类关系如下:

配置方法一

配置文件代码:

collection元素添加属性selectcolumn,使用方法和association一样,表示titles属性通过selectTitleByStaffId方法查询,column的值作为该方法的参数传递过去。

这种方法需要配置两个select语句,代码比较多,好处是灵活。

配置方法二

另一种方法是利用mybatis的自动映射功能实现一对多关联,这种方式只需要使用一条sql语句即可完成数据查询,不过collection需要明确设置属性和列的映射关系:

selectStaff中的sql语句查询结果如下:

collection result

前面两列的id和name会自动注入到Staff的id和name属性中,而title_id和title_name则注入到Title对象的titleId和titleName中,因为collection中我们已经明确配置了这种映射关系。

重点:如果collection没有配置映射关系,则Title的属性会注入失败,即使返回的数据列名称和属性名称一样。

测试代码

N+1问题

准确来说,应该是1+N问题,这个问题只存在于一对多关系中。当然并不是任何情况下都会出现这个问题,它是可解决的。

例如例子中的员工和职务的关系。无论Staff表中有多少员工,我们都只需要使用1条语句可以全部查询出来:

而对于每一个员工,我们都要额外发送一条sql语句:

换句话说, 查询所有员工只需要一条sql语句, 但查询员工的职务却需要额外的N条sql语句, 这里的N等于实际的员工个数。

如果使用log4j的话,打开日志追踪就可以很清除看到下面的日志:

简单总结

一对多关系中的两种方法,第一种方法灵活性比较高,原因在于Staff和Title分开处理,我们并不是每次都需要查询职位,但缺点是会产生N+1问题;第二种方法则每次查询Staff的同时一并查询Staff的职位,但没有N+1问题。

另外,方法一可以享受mybatis提供的懒加载机制,而第二种则没有办法使用这种机制。懒加载会在后面的文章中介绍。

所以, 使用哪一种,根据项目的实际需要来处理。

转载请注明:Pure nonsense » mybatis关联映射

喜欢 (0)
0 0 投票数
文章评分
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x
()
x