MyBatis关联映射(学习)

本文针对MyBatis的关联映射,重点在于:
(1)不同的关联关系(一对一、一对多、多对多)如何创建数据表和在对应的类中创建外键关联。
(2)如何在各个类的xml映射文件中进行配置。
在xml映射文件中确定了什么方法,这些方法如何实现。

1、一对一关联映射

1.1数据表:
tb_card 和 tb_person。
1.2数据表关联:

在tb_person表中新增一栏card_id,和tb_card中的id进行关联:

FOREIGN KEY(card_id) REFERENCES tb_card(id);

1.3类关联:

首先分别对照tb_card和tb_person创建两个类:Card和Person。然后在Person类中新增一个属性Card,用于指向某个具体的card对象。

private Card card; 

这里就开始会有一些困惑了。首先我们的Person类的其他属性都是和数据库中的tb_person一一对应的,照理来说,这里应该对应的是card_id,但实际上这里是直接指向Card对象。
1.4 xml映射文件:
1.4.1xml映射文件——CardMapper.xml:
  定义了一个selectCardById方法。根据id查询返回Card对象,实现方式如下:

SELECT * from tb_card where id = #{id}

1.4.2 xml映射文件——PersonMapper.xml:
  定义了一个selectPersonById方法。根据id查询Person。按照常理应该是返回一个Person对象,但是这里希望查询出来的结果既包含Person又能包含Card。所以需要使用到resultMap来实现。
  首先还是通过Id找到Person对象,这个Person对象是resultMap的一部分。然后根据Person对象的card_id来调用CardMapper.xml中的selectCardById方法。这样又能得到Card对象,这个对象也是resultMap的一部分。
  也就是说,我们实现了通过Card的id查询card对象,通过Person的id查询Person对象(以及Card对象)。而为什么是实现了这些查询,例如为什么不能通过Card的id来查询Person对象。而为什么后面一对多中又有类似的操作呢。类中的定义的属性跟我们后面要实现的方法有没有什么联系呢。

2、一对多关联映射

来看一下MyBatis中一对多的关联映射:
2.1 数据表:

tb_clazz 和 tb_student。
2.2 数据表关联:

在数据库中构建数据表的时候,外键在多方:
  在tb_student表中新增一栏clazz_id,和tb_clazz中的id进行关联:

FOREIGN KEY(clazz_id) REFERENCES tb_clazz(id);

2.3 类关联:

首先分别对照tb_clazz和tb_student创建两个类:Clazz和Student。这里是一对多关系,在Student类中新增一个属性Clazz,用于指向某个具体的Clazz对象。

private Clazz clazz; 

那么,我们就可以预期,在接下来的selectClazzById 和 selectStudentById方法中,结果中都需要返回Clazz和Student(或者Student的List)。
 2.4 Xml映射文件
 2.4.1xml映射文件——ClazzMapper.xml:
  定义了一个selectClazzById方法。这里还是通过clazz的id查询班级信息,但是不同于一对一映射中的CardMapper.xml,这里希望查询到的是班级和学生的信息,所以这里更类似于上面的PersonMapper.xml。
  同样是先通过clazz的id查询到tb_clazz,然后映射成为Clazz对象。然后直接还是通过原来的这个clazz的id,通过调用接下来要讲到的StudentMapper.xml中的selectStudentByClazzId方法找到对应的Student的数据并封装成一个数据列表。
  这里和一对一中的PersonMapper.xml不同的地方在于它是沿用clazz的id进行查询,而不是像PersonMapper那样利用person的id查询到person的clazz_id,然后再利用clazz_id查询出clazz。并且这里由于是一对多,得到的是一个列表。
2.4.2 xml映射文件——StudentMapper.xml:
  定义了selectStudentById方法和selectStudentByClazzId方法。这里先说后面一个方法。因为ClazzMapper.xml会调用这个方法。这个方法看起来复杂(需要查询另外一张数据表),但是其实很简单。因为我们在上面的数据表关联中已经将clazz_id,和tb_clazz中的id进行关联。换句话说,通过tb_clazz中的id来查询Student数据就相当于是根据clazz_id来查询Student数据。所以:

SELECT * FROM tb_student WHERE clazz_id = #{id}

这个方法其实在StudentMapper.xml中不是一个关键的方法,更像是ClazzMapper.xml中的selectClazzById方法所需要的一个步骤。上面也已经提到过selectClazzById中原本就能实现找到Clazz,但是为了再显示出Student才需要引用到selectStudentByClazzId这个方法。
  StudentMapper.xml中关键的方法是selectStudentById方法。
在selectStudentById方法中,希望通过学生id来查询到学生对象和班级对象。首先,如果使用SELECT * from tb_user where id= #{id}可以查询出来Student对象。
  但是这里需要将查到的student的clazz_id对应的班级的信息也都展示到结果中,所以还需要同时找到这个class对象。所以变成

   SELECT * FROM tb_clazz c,tb_student s
     WHERE c.id = s.clazz_id
      AND s.id = #{id}

然后分别映射将结果封装到Clazz和Student对象中。

3、多对多关联映射

3.1 数据表:
tb_user 和tb_order 和tb_article 。这里虽然说是多对多的关联映射,但是同时也存在一对多的关联映射。以及一个中间表tb_item。
tb_user—一对多—> tb_order <—多对多—> tb_article
3.2 数据表关联:
  在数据库中构建数据表的时候,外键在多方:
在tb_order表中新增一栏user_id,和tb_user中的id进行关联:

FOREIGN KEY(user_id) REFERENCES tb_user(id);

但是在多和多关联映射下,不需要再表中添加新的关联栏。多对多可以通过构建一个中间表来维护关系。例如订单(tb_order)和商品(tb_article)的多对多关系,这时候可以使用中间表的订单id(order_id)作为外键来参照订单表的id,中间表的商品id(article_id)作为外键来参照商品表的id。这个表tb_item是不能够单独存在的,而要依赖于订单和商品存在。
3.3 类关联:
  需要建立三个类:User、Order、Article这三个。
  虽然创建了一个中间表,但是这个中间表不需要对应的类。
  使用新的表进行映射后,还需要在对应的类中添加相应的属性,在订单Order类中添加商品属性(List

articles),而商品Article类中添加订单属性(List order)。此外,上面说过User和Order还存在一对多的关系,所以还需要在Order中添加一个User属性。Order类新增属性如下:

private User user;
private List<Article> articles;

3.4 XML 映射文件
3.4.1 xml映射文件——UserMapper.xml:
  这里定义了selectUserById方法,希望通过User的id查询到user对象,以及该对象所具有的所有订单。这还是上面的一对多的范畴。查询结构要求显示User和相关的Order对象。而要获取Order对象同样需要在OrderMapper.xml中的selectOrderByUserId中进行实现。这很容易实现。
3.4.2 xml映射文件——OrderMapper.xml:
  定义了selectOrderById和selectOrderByUserId方法。
  selectOrderByUserId在3.4.1中需要利用到。
  而selectOrderById同样要一起找到tb_user表和tb_order表的数据。但是这里还需要调用ArticleMapper.xml中的selectArticleByOrderId方法,也就是说最后还需要显示所有的商品出来。
3.4.3 xml映射文件——ArticleMapper.xml:
  多对多很复杂,但是查询看起来确实比较简单,利用了子查询。在ArticleMapper.xml中,selectArticleByOrderId中

    SELECT * FROM tb_article WHERE id IN(
        SELECT article_id FROM tb_item WHERE order_id = #{id}
    )

可以看到,在这里才利用了tb_item这个表,先通过order_id查询到所有的article_id。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值