Mybatis-多表联查

在数据库查询中,很多时候不只是查询一张表,而是需要将多张表结合起来才能获得需要的数据,下面介绍在mybatis中怎么实现多表联查(前提是所有的依赖均已配置完成)

一、步骤一:创建pojo实体类

将需要用到的表全部创建成java的实体类,导入lombok依赖(自动生成get、set等方法)
User 用户表 Order 订单表

@Data
public class User {
    
    
    private Integer ID;
    private String username;
    private String PASSWORD;
    private String sex;
    private Date brithday;
    private String address;
}

二、步骤二:明确两个实体类之间的关系

一个用户可以有多条订单,而一条订单只属于一个用户
所以;:用户对订单是1对多的关系
 
在设计数据库时(黄色部分):在多的一方(tb_order)中添加一个外键,与tb_user的主键对应(图中为uid)
 
在设计java对象时(红色部分): 需要根据题目进行pojo类的编写(具体看步骤三)

在这里插入图片描述


三、步骤三:修改pojo实体类

先分析清楚题目 如:

①:根据id查询订单以及订单的所属用户信息
=> 返回的数据是tb_order表中的数据+tb_user表中的数据,需要修改的实体类是Order,因为是根据order的id查询的


//需要在Order的实体类中引入User对象
public class Order {
    
    
    private Integer id;
    private Integer userid;
    private Date createtime;
    private String state;

//    多对一
    private User user = new User();
}

②:根据用户id查询她的各类订单
=>返回的数据是tb_user+tb_order表中的数据,但是不同与上面的是:由于订单有多条所以订单需要用集合来装,而查询出的数据是要根据用户的id查询所有需要修改User类

// 需要在User表中的实体类中引入数据类型为Order的集合
public class User implements Serializable {
    
    
    private Integer ID;
    private String username;
    private String PASSWORD;
    private String sex;
    private Date brithday;
    private String address;

//    一对多
    private List<Order> orders = new ArrayList<>();
}


四、步骤四:编写Mapper接口

public interface UserMapper {
    
    
//    通过订单id查询订单详情以及所属用户
    Order selectOrderAndInfoById(@Param("oid") int id);
//    通过用户id查询该用户的所有订单
    User selectByUserIdForOrder(@Param("uid") int id);
//    根据id查询用户
    User selectUserByid(@Param("uid") int id);
}

五、步骤五:编写Mapper映射文件

需要指定该映射文件是步骤四的Mapper,在namespace中指定

重点来了:

题目1:通过订单id查询订单详情以及所属用户

需要知道的是我们关联的是两张表,如果直接用下面的sql语句则只能查出订单的信息而订单所属用户则为空,这是因为在执行过程中Order会自动映射到tb_order的内容,但是在Order表中定义的User对象则无法自动映射到tb_user表中的内容

SELECT  u.ID ,u.username,u.PASSWORD,u.sex,u.brithday,u.address,o.id oid,o.userid,o.createtime,o.state
FROM tb_user u JOIN tb_order o
ON u.ID  = o.userid
WHERE u.id= #{uid}

所以我们得手动映射User类,需要使用到resultMap
总体代码如下:

 <!--  todo  根据id查询订单以及对应的用户 -->
    <sql id="selectById">
        u.ID ,u.username,u.PASSWORD,u.sex,u.brithday,u.address,
        o.id oid,o.userid,o.createtime,o.state
    </sql>
    <resultMap id="selectParent" type="Order">
        <id property="id" column="oid"/>
        <result property="userid" column="userid"/>
        <result property="createtime" column="createtime"/>
        <result property="state" column="state"/>
    </resultMap>
    <resultMap id="selectChildren" type="Order" extends="selectParent">
        <association property="user" javaType="User" select="selectUserByid" column="userid"/>
    </resultMap>
    <select id="selectOrderAndInfoById" resultMap="selectChildren">
        SELECT
        <include refid="selectById"/>
        FROM tb_user u JOIN tb_order o
        ON u.ID = o.userid
        WHERE o.id = #{oid}
    </select>

    <!--    根据id查询用户-->
    <select id="selectUserByid" resultType="User">
        SELECT * FROM tb_user WHERE ID = #{uid}
    </select>

selectParent为手动映射的Order类的Map,selectChildren为手动映射的User类的Map,由于需要返回的订单类的数据所有type中填写Order类,children继承了parent那么children中也会有parent的映射,所有selectChildren的map中就有了Order+User的映射
在这里插入图片描述
这个时候再<select>标签resultMap中只需要传入selectChildren就可以了

<association property="user" javaType="User" select="selectUserByid" column="userid"/>

association :因为在Order类中的User对象是个,所以使用该关键字
property:对应Order表中的创建的User对象名
javaType:property对应的数据类型
select:就是指映射user对象去改方法中找,刚刚selectUserByid方法返回的就是一个User对象,这样就免去了手动一 一映射的麻烦
column:但是selectUserByid需要传入一个参数,这里传入的userid是从Order中查询得到的然后再传给该方法去查询对应的User


题目2:通过用户id查询用户信息以及她所有的订单

学会了上面的知识后,这里就只是发生了一点点的变化

同样也是,是根据用户的id查询所以需要在User类中进行操作,而一个用户有多条订单,所以需要在用户类User中定义一个Order类型的集合,mybatis也只能映射User类和tb_user表,无法映射Order类和tb_order表,所以我们也需要手动映射

总体代码如下:

 <!--    todo 根据用户id查询订单 -->

    <resultMap id="Userparent" type="User">
        <id column="ID" property="ID"/>
        <result column="username" property="username"/>
        <result column="PASSWORD" property="PASSWORD" />
        <result column="sex" property="sex" />
        <result column="brithday" property="brithday" />
        <result column="address" property="address" />

        <collection property="orders" ofType="Order" >
            <id column="oid" property="id"/>
            <result column="userid" property="userid"/>
            <result column="createtime" property="createtime"/>
            <result column="state" property="state" />
        </collection>

    </resultMap>
    <select id="selectByUserIdForOrder" resultMap="Userparent" parameterType="int">
        SELECT <include refid="selectById"/>
        FROM tb_user u JOIN tb_order o
        ON u.ID  = o.userid
        WHERE u.id= #{uid}
    </select>

与上面不同的是集合映射使用关键字collection ,并且返回类型不再使用type而是使用ofType来指定
前面题目一映射是使用的继承,现在题目二映射是直接在父映射中继续映射,并且没有使用方法


六、补充

id 唯一标识符
type 写返回的类的类名
<result/> 对非主键的映射
<id/> 对主键的映射
property 关联属性名 也就是User类中定义的各属性
column 关联属数据库的字段
javaType 关联属性的数据类型 在集合属性时不要写,但是在题目一的情况下就需要使用
ofType 关联属性的数据类型 在集合属性时写,但是在题目一的情况下就不要使用

猜你喜欢

转载自blog.csdn.net/qq_52998673/article/details/128121638
今日推荐