MyBatis 关联查询的实现:一对多

有2个实体:用户、订单,一个用户可以拥有多个订单,同时这多个订单属于一个用户,即一对多。

 

user_tb:

 

 

order_tb:

在“多”的一方(order)添加“一”的一方(user)的主键(user_id)作为外键。

 

 


 

 

使用嵌套结果

(1)给2个实体都编写pojo类,需要在“一”的一方写个List来关联“多”的一方

package com.chy.pojo;

public class Order {
    private Integer no;
    private Integer userId;
    private Integer goodsId;
    private Integer goodsAmount;

    public Integer getNo() {
        return no;
    }

    public void setNo(Integer no) {
        this.no = no;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public Integer getGoodsId() {
        return goodsId;
    }

    public void setGoodsId(Integer goodsId) {
        this.goodsId = goodsId;
    }

    public Integer getGoodsAmount() {
        return goodsAmount;
    }

    public void setGoodsAmount(Integer goodsAmount) {
        this.goodsAmount = goodsAmount;
    }

    @Override
    public String toString() {
        return "Order{" +
                "no=" + no +
                ", userId=" + userId +
                ", goodsId=" + goodsId +
                ", goodsAmount=" + goodsAmount +
                '}';
    }
}

 

package com.chy.pojo;

import java.util.List;

public class User {
    private Integer id;
    private String username;
    private String password;
    private String tel;
    private String address;
    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 String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    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 + '\'' +
                ", password='" + password + '\'' +
                ", tel='" + tel + '\'' +
                ", address='" + address + '\'' +
                ", orderList=" + orderList +
                '}';
    }
}

toString()只是为了方便测试、调试,后期可以去掉。

 

 

(2)给“一”的一方写Mapper接口、xml映射文件

package com.chy.mapper;

import com.chy.pojo.User;

public interface UserMapper {
    public User queryUserById(Integer id);
}

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper  PUBLIC
        "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chy.mapper.UserMapper">
    <select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder">
        SELECT user_tb.*,order_tb.* FROM user_tb,order_tb WHERE user_tb.id=#{id} AND order_tb.user_id=user_tb.id
     </select>
    <resultMap id="userResultWithOrder" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="tel" column="tel"/>
        <result property="address" column="address"/>
        <collection property="orderList" ofType="order">
            <id property="no" column="no"/>
       <result property="userId" column="user_id" /> <result property="goodsId" column="goods_id" /> <result property="goodsAmount" column="goods_amount" /> </collection>
</resultMap> </mapper>

因为关联的是集合(List),所以用<collection>。

  • property指定表示关联对象的成员变量名
  • ofType指定返回的数据类型,注意不是list。
  • 子元素<id>、<result>配置关联对象的映射。

 

所谓关联查询,是查询结果中同时包含双方(2张表)的多个字段,

如果只查询一张表的字段,比如说只查询某个用户的订单,不查询此用户本身的信息,直接根据外键user_id查order_tb表,不需要查user_tb,不必使用关联查询,写个OrderMapper接口、OrderMapper.xml就ok。

 

 

(3)使用

package com.chy.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

 

package com.chy.test;

import com.chy.mapper.UserMapper;
import com.chy.pojo.User;
import com.chy.utils.MyBatisUtils;
import org.apache.ibatis.session.*;

public class Test {
    public static void main(String[] args) {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.queryUserById(1);
        System.out.println(user);
        sqlSession.close();
    }
}

 

 


 

 

使用嵌套查询

与嵌套结果大体相同,不同的只有第二步:

(二)给双方都编写Mapper接口、映射文件

package com.chy.mapper;

import com.chy.pojo.Order;

public interface OrderMapper {
    //根据orderId查询订单信息
    public Order queryOrderByUserId(Integer userId);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper  PUBLIC
        "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chy.mapper.OrderMapper">
    <select id="queryOrderByUserId" parameterType="integer" resultMap="orderMap">
        SELECT * FROM order_tb WHERE user_id=#{id}
    </select>
    <resultMap id="orderMap" type="order">
        <id property="no" column="no"/>
        <result property="userId" column="user_id"/>
        <result property="goodsId" column="goods_id"/>
        <result property="goodsAmount" column="goods_amount"/>
    </resultMap>
</mapper>

 

 

package com.chy.mapper;

import com.chy.pojo.User;

public interface UserMapper {
    public User queryUserById(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper  PUBLIC
        "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chy.mapper.UserMapper">
    <select id="queryUserById" parameterType="integer" resultMap="userResultWithOrder">
        SELECT * FROM user_tb WHERE id=#{id}
     </select>
    <resultMap id="userResultWithOrder" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="tel" column="tel"/>
        <result property="address" column="address"/>
        <collection property="orderList" column="id" ofType="order" select="com.chy.mapper.OrderMapper.queryOrderByUserId"/>
    </resultMap>
</mapper>

column指定向子查询传递的参数是当前表的哪一列。

 

 


 

 

<resultMap>中的映射问题

我在<resultMap>中使用了子元素<id>、<result>配置了所有的表字段——pojo类属性之间的映射,

 

其实只要表字段、pojo类属性的名称一致,就不必配置,比如

<resultMap id="userResultWithOrder" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="tel" column="tel"/>
        <result property="address" column="address"/>
        <collection property="orderList" column="id" ofType="order" select="com.chy.mapper.OrderMapper.queryOrderByUserId"/>
    </resultMap>

红色部分完全可以省略,因为默认的映射就是pojo类属性、表字段名称一致。

 

 

如果部分不一致,只需配置不一致的部分,比如只有用户id的不一致:

<resultMap id="userResultWithOrder" type="user">
        <id property="id" column="user_id"/>
        <collection property="orderList" column="id" ofType="order" select="com.chy.mapper.OrderMapper.queryOrderByUserId"/>
    </resultMap>
posted @ 2020-01-08 14:36  chy_18883701161  阅读(3359)  评论(0编辑  收藏  举报