实际项目开发中,多对多关系也是非常常见的关系,比如,一个购物系统中,一个用户可以有多个订单,这是一对多的关系:一个订单中可以购买多种商品,一种商品也可以属于多个不冋的订单,订单和商品就是多对多的关系。对于数据库中多对多关系建议使用一个中间衰来俊护关系,中间表中的订单id作为外键参照订单表的id,商品id作为外健件照商品表的id。
下面我们就用一个简单示例来看看MyBatis怎么处理多对多关系.
创建用户表tb_user
创建商品表tb_article
创建订单表tb_order
创建中间表tb_item
tb_order表的user_jd作为外键参照tb_user表的主越id. tb_item表作为中间表,用来维护tb_article和命_order的多对多关系,tb_item表的order_id作为外键参照tb_order表的主健id. aitide.id作为外键参照tb_article表的主键id。
接下来,创建一个User对象、一个Article对象和一个Order对象分别映射tb_user,tb_article和 tb_order 表。
订单和用户是多对一的关系,一个订単只属于一个用户,在Order类中定义了一个user属性,用来映射多对一的关联关系,表示该订单的用户,订単和商品是多对多的关系,即一个订单中可以包含多种商品,在Order类中定义了一个articles属性,该属性是一个List集合,用来映射多对多的关联关系,表示一个订単中包含多种商品。
创建Article实体
商品和订单是多对多的关系,即一种商品可以出现在多个订单中。在Article类中定义了一个orders 属性,该属性是一个List集合,用来映射多对多的关联关系,表示该商品关联的多个订单。
结果映射xml
UserMapper.xml中定义了一个〈select./>,其根据id査询用户信息。由于User类除了简单的属性 id、usemame、loginname、password、phone 和 address 之外,还有一个关联对象 orders.所以返回的是一个名为userResultMap的resultMap.由于orders是一个List集合,因此userResultMap中使用了Collection..•/>元素映射一对多的关联关系,select属性表示会使用column属性的id值作为参数执行OrderMapper中定义的selectOrderByUserld査询该用户所下的所有订单,査询出的数据将被封装到property表示的orders对象当中。注意,一对多使用的都是lazy (懒加载)。
订单order结果映射xml
<!—注意,如果査询出来的列同名,例如tb_user表的id和tb_order表的id都是id,同名,则需要使用别名区分一>
OrderMapper.xml 中定义了 一个<select id=" selectOrderByUserld".. />,其根据用户 id 査询订单信息,返回的是简单的Order对象。
还定义了一个<select id=" selectOrderByld".../> 其根据订单id査询订单信息,由于Order类和用户是多对一关系,和商品是多对多关系,而多对一通常都是立即加载,因此SQL语句是一条关联了 tb_user和tb_order的多表査询语句。査询结果返回一个名为orderResultMap的resultMap。orderResultMap中使用了<association.../>元素映射多对一的关联关系,其将査询到的用户信息装载到Order对象的user属性当中;orderResultMap中还使用了<collection../>元素映射多对多的关联关系,select属性表示会使用column属性的oid值作为参数执行ArticleMapper中定义的selectArticleByOrderld査询该订单中的所有商品,査询出的数据将被封装到property表示的articles对象当中。注意,一对多使用的都是lazy (懒加载)。
提示:因为多表查询返回的结果集中tb_user有个id列,tb_order也有个id列,当列同名时,MyBatis使用的元素中的column属性如果是id,则MyBatis会默认使用查询出的第一个id列.为了区分同名的列,最好的方法是给列取一个别名。sql语句中的o.id AS oid, resultMap中的column="oid”就是指使用的是tb_order表的id值 。