MyBatis(五)——关联映射

1.一对一

在任意一方引入对方主键作为外键

例如有IdCard(id,code)和Person(id,name,id_card),IdCard.id和Person.id_card关联

通过PersonMapper查询Person,其中又涉及到实体类IdCard,这就是所谓的一对一关系映射。

package com.mybatis.bean;

public class IdCard {

    private Integer id;
    private String code;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    @Override
    public String toString() {
        return "IdCard [id=" + id + ", code=" + code + "]";
    }
}

/*
create table tb_idcard(
    id int primary key auto_increment,
    code varchar(18)
);

insert into tb_idcard(code) values('44422211111102623X');
insert into tb_idcard(code) values('444222111111023141');





*/
IdCard.java
package com.mybatis.bean;

public class Person {

    private Integer id;
    private String name;
    private IdCard card;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public IdCard getCard() {
        return card;
    }
    public void setCard(IdCard card) {
        this.card = card;
    }
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", card=" + card + "]";
    }
    

}
/*
create table tb_person(
id int primary key auto_increment,
name varchar(32),
card_id int unique,
foreign key(card_id) references tb_idcard(id)
);

insert into tb_person(id,name,card_id) values(null,'守林鸟',2);
insert into tb_person values(null,'灰太狼',1); 

*/
Person.java

(1)嵌套查询,IdCardMapper.xml和PersonMapper.xml的配置如下:

    <!-- public IdCard findCodeById(Map<String, Object> map); -->
    <select id="findCodeById" resultType="com.mybatis.bean.IdCard">
        select * from tb_idcard where id=#{id}
    </select>
    <!-- public Person findPersonById(Map<String, Object> map); -->
    <select id="findPersonById" parameterType="Integer" resultType="IdCardWithPersonResult">
        select * from tb_person where id=#{id}
    </select>
    
    <resultMap type="com.mybatis.bean.Person" id="IdCardWithPersonResult">
        <id property="id" column="id"></id><!-- 主键 -->
        <result property="name" column="name"/>
        <association property="card" column="card_id" javaType="com.mybatis.bean.IdCard"
        select="com.mybatis.mapper.IdCardMapper.findCodeById"/>
    </resultMap>

Person封装了IdCard,通过<resultMap>的子元素<association>封装另一条语句的查询语句,其中用select属性连接到另一条SQL语句,即运行了多条SQL语句。

(2)嵌套结果

只执行一条SQL语句,就是传统的MySQL中的查询语句,用<association>将一些属性弄成映射关系。

    <select id="findPersonById" resultMap="IdCardResult">
        <!-- select * from tb_person where id=#{id}  -->
        select p.*,idcard.code 
        from tb_person p,tb_idcard idcard 
        where p.card_id=idcard.id and p.id=#{id} 
    </select>

    <resultMap type="com.mybatis.bean.Person" id="IdCardResult">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="card" javaType="com.mybatis.bean.IdCard">
            <id property="id" column="card_id"></id>
            <result property="code" column="code"/>
        </association>
    </resultMap>

这一条语句[select p.*,idcard.code from tb_person p,tb_idcard idcard where p.card_id=idcard.id and p.id=1]和[select p.id,p.name,p.card_id,i.code from tb_person p left join tb_idcard i on p.card_id=i.id where p.id=1]效果一样。

显然,对于大型数据集合,嵌套查询会导致成百上千关联的SQL语句被执行,从而极大消耗了数据库性能并且降低查询效率,显然嵌套结果更加主流,不难看出对SQL语句的掌握要求比较高。

 

2.一对多

例如一个用户有多个订单,查用户的时候顺便把订单查出来,用<resultMap>的子元素<collection>实现,其中有一个ofType属性,这个与一对一查询的javaType属性对应。

package com.mybatis.bean;

import java.util.List;

public class User {

    private Integer id;
    private String username;
    private List<Order> orderList;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public List<Order> getOrderList() {
        return orderList;
    }
    public void setOrderList(List<Order> orderList) {
        this.orderList = orderList;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", orderList=" + orderList + "]";
    }
}
/*
create table tb_user(
id int primary key auto_increment,
username varchar(32)
);

insert into tb_user values('1','灰太狼');
insert into tb_user values('2','守林鸟');
insert into tb_user values(null,'霸王别鸡');

*/
User.java
package com.mybatis.bean;

public class Order {

    private Integer id;
    private String number;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
    @Override
    public String toString() {
        return "Order [id=" + id + ", number=" + number + "]";
    }

}

/*
create table tb_order(
id int primary key auto_increment,
number varchar(32) not null,
user_id int not null,
foreign key(user_id) references tb_user(id)
);
insert into tb_order values('1','10086','1');
insert into tb_order values(null,'10087',3);
insert into tb_order values(null,'10088',2);

*/
Order.java
    <!-- public User findUserWithOrders(HashMap<String, Object> map); -->
    <select id="findUserWithOrders" resultMap="UserWithOrderResult">
        select u.*,o.id as order_id,o.number from tb_user u,tb_order o
        where u.id=o.user_id and u.id=#{id}
    </select>
    
    <resultMap type="com.mybatis.bean.User" id="UserWithOrderResult">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <!-- 一对多关系映射 -->
        <collection property="orderList" ofType="com.mybatis.bean.Order">
            <id property="id" column="order_id"></id>
            <result property="number" column="number"/>
        </collection>
    </resultMap>

 

3.多对多

通常用一个中间表来维护,例如有订单表tb_order(id,number,user_id),中间表tb_orderitem(id,order_id,product_id),商品表tb_product(id,name),中间表的order_id参照订单表的id,product_id参照商品表的id。

在上面的表的基础上再创建tb_product和tb_orderitem。

create table tb_product(
id int primary key auto_increment,
name varchar(32)
);

insert into tb_product values('1','Java从入门到入土');
insert into tb_product values(null,'C++从入门到放弃');
insert into tb_product values(null,'MySQL从删库到跑路');
insert into tb_product values(null,'ACM竞赛入门指导');



create table tb_orderitem(
id int primary key auto_increment,
order_id int,
product_id int,
foreign key(order_id) references tb_order(id),
foreign key(product_id) references tb_product(id)
);

insert into tb_orderitem values('1','1','1');
insert into tb_orderitem values('2','1','3');
insert into tb_orderitem values('3','3','3');

配置多对多的关联映射,也是用<collection>,这里用的是嵌套结果的方式。

<mapper namespace="com.mybatis.mapper.OrderMapper">
    <select id="findOrdersWithProduct" resultMap="OrderWithProductResult">
        select o.*,p.id as pid,p.name from tb_order o,tb_product p,tb_orderitem oi
        where oi.order_id=o.id and oi.product_id=p.id and o.id=#{id}
    </select>
    
    <resultMap type="Order" id="OrderWithProductResult">
        <id property="id" column="id"/>
        <result property="number" column="number"/>
        <!-- 多对多关联映射,嵌套结果,collection -->
        <collection property="productList" ofType="Product">
            <id property="id" column="pid"/>
            <result property="name" column="name"/>
        </collection>
    </resultMap>
</mapper>

 

 


 参考&引用

《JavaEE企业级应用开发教程》——黑马程序员

posted @ 2020-06-04 21:54  守林鸟  阅读(277)  评论(0编辑  收藏  举报