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属性中,这样的作的目的也是方便对查询结果集进行遍历查询.

原文地址:https://www.cnblogs.com/64Byte/p/13038310.html