zoukankan      html  css  js  c++  java
  • Mybatis的关联查询

    转载:https://blog.csdn.net/z_ssyy/article/details/81706876

    首先要了解对象的三种关联方式

    *数据库表的关联关系有三种,一对一,一对多,多对多
    一对一   是通过在任意一方的主键,引入对方主键作为外键来实现的,就是说主键与外键为同一字段
    一对多   是通过在“多”的一方,添加“一”的一方的主键作为外键
    多对多   是通过一张中间关系表,引入两张表的主键作为外键,两个主键成为联合主键或使用新的字段作为主键

    *在java类中关联关系也有三种,一对一,一对多,多对多
    一对一   在本类中定义对方类型的对象,如A类中定义B类类型的属性b,B类中定义A类类型的属性a
    一对多   一个A类类型对应多个B类类型的情况,需要在A类中以集合的方式引入B类类型的对象,在B类中定义A类类型的属性a
    多对多   在A类中定义B类类型的集合,在B类中定义A类类型的集合

     表与表之间的关联:

    • association:用于映射关联单个对象信息
    • collection:对关联查询到的多条记录映射到集合对象
    • property:关联的属性名,就是将用户对象关联到某个表的那个属性
    • column:数据库中的字段名
    • javaType: 属性的类型
    • ofType: 指明集合中的元素的类型

     一对一查询

      需求:根据订单id查询订单信息,以及关联的用户信息

    Order类:

    public class Order {
        private Integer id;
        private Date createtime;
        private String state;
        //关联属性
        private User user;  //订单属于哪一个用户

    Order表的Sql映射文件:

    <!-- 定义一个属性与列的映射 -->
    <resultMap type="Order" id="OrderAndUserMap">
        <!-- order 表的映射 -->
        <id column="id" property="id"/>
        <result column="createtime" property="createtime"/>
        <result column="state" property="state"/>
        <!-- 配置关联属性user的信息
        association:用于映射关联单个对象信息 
        property:关联的属性名,就是将用户对象关联到Order的那个属性
        avaType: 属性的类型
         -->
        <association property="user" javaType="User">
            <id column="u_id" property="UserId"/>
            <result column="username" property="name"/>
                  <result column="password" property="password"/>
                  <result column="sex" property="sex"/>
                  <result column="address" property="address"/>
                  <result column="brithday" property="brithday"/>
        </association>
    </resultMap>

    SQL语句的定义:

    <!-- 查询一个这个订单的用户信息 -->
    <select id="findUserByOrderId" parameterType="int" resultMap="OrderAndUserMap">
            select <include refid="UserOrderColumn"/> from t_user u ,t_order o where u.id = o.USID and o.ID = #{id}
    </select>
    <!-- id名一样,会取第一个值,取个别名避免错误 -->
    <sql id="UserOrderColumn">
            u.id u_id,u.username,u.password,u.sex,u.brithday,u.address,o.id,o.createtime,o.state
    </sql>

    OrderMapper接口:

    //查询一个这个订单的用户信息
    Order findUserByOrderId (int oid);

    测试代码:

    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    Order order = orderMapper.findUserByOrderId(1);
    System.out.println(order);
    sqlSession.close();

    第二种方式:(推荐)

    User表的Sql映射文件:(有根据id查询的语句)

    //UserMapper.java接口
        // 根据id查询用户: User queryUserById(int id) throws Exception;
    <mapper namespace="com.mybatis.mapper.UserMapper">//地址
    <!-- 使用resurtMap,映射属性 --> <resultMap type="User" id="UserMap"> <id column="id" property="UserId"/> <result column="username" property="name"/> </resultMap> <!-- 根据id查询 --> <select id="queryUserById" parameterType="int" resultMap="UserMap" > select * from t_user where id = #{id} </select>

    修改Order表的Sql映射文件:

    select: namespace.statementId , 关联属性通过哪一个statement查询 根据用户id查询用户信息
    column: 列名, 从主查询,吧哪一个列的值作为参数,传递给调用的statement

    <select id="findUserByOrderId" parameterType="int" resultMap="OrderAndUserMap2">
        select * from t_order where id = #{id}
    </select>
    <resultMap type="Order" id="OrderAndUserMap2">
        <!-- order 表的映射 -->
        <id column="id" property="id"/>
        <result column="createtime" property="createtime"/>
        <result column="state" property="state"/>
        <!-- 配置关联属性 -->
        <association property="user" javaType="User"
            select="com.mybatis.mapper.UserMapper.queryUserById" column="usid"> (关联order表的id字段)
        </association>
    </resultMap>

    测试:执行了两条语句,简化代码

    一对多查询

      需求:查询用户,及用户下的所有订单信息

    User类:

    public class User {
        private Integer UserId;
        private String name;
        private String password;
        private String sex;
        private Date brithday;
        private String address;
    //new出对象,避免空指针异常
        private List<Order> orders = new ArrayList<>();

    User表的Sql映射文件:

    <!-- 定义一个属性与列的映射 -->
    <resultMap type="User" id="UserAndOrderMap">
        <!-- 映射的User -->
        <id column="id" property="UserId"/>
        <result column="username" property="name"/>
                 <result column="password" property="password"/>
                 <result column="sex" property="sex"/>
                 <result column="address" property="address"/>
                 <result column="brithday" property="brithday"/>
        <!-- 配置集合关联属性 collection属性 
        property: 关联属性名: ofType: 集合元素的类型, 
            列映射的Order类 -->
        <collection property="orders" ofType="Order" >
            <id column="o_id" property="id"/>
            <result column="createtime" property="createtime"/>
            <result column="state" property="state"/>
        </collection>
    </resultMap>

    SQL语句的定义:

    <!-- 根据一个用户id查询所有订单信息 -->
    <select id="findInfoByorderId" parameterType="int" resultMap="UserAndOrderMap">
        select <include refid="UserOrderColumn"/> from t_user u ,t_order o where u.id = o.USID and u.ID = #{UserId}
    </select>
    <!-- id名一样,会取第一个值,取个别名避免错误 -->
    <sql id="UserOrderColumn">
        u.id,u.username,u.password,u.sex,u.brithday,u.address,o.id o_id,o.createtime,o.state
    </sql>

    UserMapper接口:

    //根据一个用户id查询所有订单信息
        User findInfoByorderId(int oid) throws Exception;

    测试:

    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.findInfoByorderId(27);
    System.out.println(user);

    多对多查询

      需求:根据用户id,查询响应的订单,订单详情,商品详情信息

    映射思路:

      将用户信息映射到user中。

      在user类中添加订单列表属性List<Orders> orders,将用户创建的订单映射到orders

      在Orders中添加订单明细列表属性List<OrderDetail>orderdetials,将订单的明细映射到orderdetials

    实体类:

    User表关联Order表:

    public class User {
        private Integer UserId;
        private String name;
        private String password;
        private String sex;
        private Date brithday;
        private String address;
        private List<Order> orders = new ArrayList<>();

    Order表关联Orderdetail表:

    public class Order {
        private Integer id;
        private Date createtime;
        private String state;
        //关联属性, 订单详情  集合关联属性
        private List<Orderdetail> orderdetails = new ArrayList<>();
        

    Orderdetail表关联product表:

    public class Orderdetail {
        private Integer id;
        private Integer num;
        private Double price;
        //关联属性  商品   单个关联属性
        private Product product;

    UserMapper.java接口方法:

    //根据id查询用户以及用户所有的订单信息,以及订单详情及商品信息(方法名越长,越方便理解)
        User findUserAndOrderAndOrderdetailAndProductById(int id) throws Exception;

     User表的Sql映射文件:

    <resultMap type="User" id="userOrderOrderdetailProductMap">
        <!-- order 表的映射 -->
        <id column="id" property="UserId"/>
        <result column="username" property="name"/>
                 <result column="password" property="password"/>
                 <result column="sex" property="sex"/>
                 <result column="address" property="address"/>
                 <result column="brithday" property="brithday"/>
        <!-- 配置关联Order属性 -->
        <collection property="orders" ofType="Order" >
            <id column="o_id" property="id"/>
            <result column="createtime" property="createtime"/>
            <result column="state" property="state"/>
            <!-- 配置关联orderdetails属性 -->
                <collection property="orderdetails" ofType="Orderdetail" >
                <id column="od_id" property="id"/>
                <result column="num" property="num"/>
                <result column="price" property="price"/>
                    <!-- 关联属性: product 单个的关联属性-->
                    <association property="product" javaType="Product">
                      <id column="p_id" property="id" />
                      <result column="name" property="name" />
                      <result column="p_price" property="price" />
                      <result column="description" property="description" />
                    </association>
                </collection>
        </collection>
    </resultMap>

    sql语句的定义:

    <!-- 根据id查询用户以及用户所有的订单信息,以及订单详情及商品信息(多对多查询 -->
        <select id="findUserAndOrderAndOrderdetailAndProductById" parameterType="int" 
      resultMap
    ="userOrderOrderdetailProductMap"> select <include refid="userOrderOrderdetailProductColumn"/> from t_user u join t_order o on u.id = o.usid join t_orderdetail od on o.id = od.id join t_product p on od.productid = p.id where u.id = #{id} </select> <sql id="userOrderOrderdetailProductColumn"> u.*, o.id o_id,o.CREATETIME,o.STATE,od.id od_id, od.num,od.price, p.id p_id,p.name,p.price p_price,p.description </sql>

    测试:

    SqlSession sqlSession = MybatisUtil.openSession();
    //根据id查询用户以及用户所有的订单信息,以及订单详情及商品信息(多对多查询
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.findUserAndOrderAndOrderdetailAndProductById(23);
    System.out.println(user);
    sqlSession.close();

    总结

    resultMap:

      使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

    association:

      作用:将关联查询信息映射到一个对象中。

      场合:为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的关联属性中,

    比如:查询订单及关联用户信息。

    collection:

      作用: 将关联查询信息映射到一个list集合中。

      场合: 为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,

    比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,

    将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询.

  • 相关阅读:
    MTK Android 源码目录分析
    MTK Android 平台语言支持状态
    开坑了啦啦啦..
    codeforces泛做..
    用介个新的blog咯..
    【UR #5】怎样跑得更快
    【UR #5】怎样提高智商
    【集训队互测2016】消失的源代码
    口胡
    [八省联考2018]劈配
  • 原文地址:https://www.cnblogs.com/64Byte/p/13038310.html
Copyright © 2011-2022 走看看