MyBatis中association(多对一)和collection(一对多)的联表查询

MyBatis中联表查询的实现

在使用数据库时,我们经常会需要联表查询,把数据库b的信息整合到数据库a一并查询,就类似于老师于学生,工作和员工的关系。

Mybatis就提供了一些这样的配置标签来帮助我们进行联表操作,简化我们的操作:associationcollection

每个标签还都分别有两种查询方法:1:按查询嵌套处理 2:按结果嵌套处理

1:association(多对一)

association对象主要针对多个字段和同一个字段都有联系时,也就是多对一的情况。

MySQL数据库架构:
(数据库中的mybatis_test在下文会解释成user表)
在这里插入图片描述
实体类:

@Data //@Data注解可以帮助我们免去抒写GET,SET,ToString,有参,无参构造
//需要安装Lombok插件和maven依赖(或者jar包)
public class Work  {
   private int id;
   private String name;
}
@Data
public class User {
   private int id;
   private String name;
   //多个员工对应一个工作,即多对一
   private Work work;
}

mapper

public interface UserMapper {
	public List<User> getUser();
}
public interface WorkMapper {
}

MyBatis 核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    <typeAliases>
        <typeAlias type="com.nicht.pojo.User" alias="User"/>
        <typeAlias type="com.nicht.pojo.Work" alias="Work"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/web_work?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC&amp;rewriteBatchedStatements=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123321"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--这里填写和mapper的xml的路径来进行配置连接 -->
        <mapper resource="UserMapper.xml"/>
        <mapper resource="WorkMapper.xml"/>
    </mappers>
</configuration>

1.按查询嵌套处理

按查询嵌套处理的方式:

先查询a表,然后根据a表中提供的信息再查询b表,最后把b表中查询的内容拼接到a表中,然后得出查询结果

<?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文件路径-->
<mapper namespace="com.nicht.mapper.UserMapper">

    <select id="getUser" resultMap="UserWork">
        select * from web_work.mybatis_test
    </select>
    <resultMap id="UserWork" type="User">
        <association property="work" column="wid" javaType="Work" select="getWork"/>
        <!--property:User类中对应的元素,column:表中所对应的字段  
         	javaType:所查询到的字段所返回对应的实体类
         	select:所要使用的查询标签的id
         	根据这些属性的定义,MyBatis就会去调用下面那个select标签
         	把查询到的结果拼接到上面所查询的表中
         	且上面所查询到的coulumn就会传递到下面的select中,填入参数
         	当column只有一个的时候,上下id不一样也不会引起冲突,就一个嘛-->
         	
    </resultMap>
    
    <select id="getWork" resultType="Work">
        select * from web_work.work where id = #{id}
    </select>

</mapper>

测试:

public class test {
    @Test
    public void selectUser() {
        SqlSession session = MyBatisUtils.getSession();
        //UserMapper.class中用到了反射的原理
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.getUser();
        for (User user : users){
            System.out.println(user);
        }

        session.close();
    }
}

2.按结果嵌套处理

按查询嵌套处理的方式:
一开始就把a,b表中的内容查询出来,然后再根据查出来的字段分配好对应的实体类属性,虽较为理解,但sql语句抒写复杂。

<?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文件路径-->
<mapper namespace="com.nicht.mapper.UserMapper">

<select id="getWork2" resultMap="UserWork2" >
  select m.id mid, m.name mname , w.name wname
  from  mybatis_test m,Work w
  where m.wid = w.id
</select>

<resultMap id="StudentTeacher2" type="Student">
   <id property="id" column="mid"/>
   <result property="name" column="mname"/>
   <association property="work" javaType="Work">
       <result property="name" column="wname"/>
   </association>
</resultMap>

</mapper>

测试页面和上面的按查询嵌套方式处理一样

2:collection(一对多)

collection标签对应的就是一个字段和多个其他字段都有联系时,也就是一对多的情况。
在一对多的案例中,我们就是主要对Work表作为主要操作的地方了

实体类:

@Data //@Data注解可以帮助我们免去抒写GET,SET,ToString,有参,无参构造
//需要安装Lombok插件和maven依赖(或者jar包)
public class Work  {
   private int id;
   private String name;
   //一个工作对应多个员工
    private List<User> users;
}
@Data
public class User {
   private int id;
   private String name;
   private int wid;
  
}

mapper

public interface UserMapper {
	
}
public interface WorkMapper {
	public Work getWork(int id);
}

1.按结果嵌套处理

记得在mybatis核心配置文件中配置mapper

<mapper namespace="com.kuang.mapper.TeacherMapper">

   <!--
           	   集合使用collection!
               JavaType和ofType都是用来指定对象类型的
               JavaType是用来指定pojo中属性的类型
               ofType指定的是映射到list集合属性中pojo的类型。
   -->
   <select id="getWork" resultMap="WorkUser">
      select m.id mid, m.name mname , w.name wname, w.id wid
      from mybatis_test m,user u
      where u.wid = w.id and w.id=#{id}
   </select>

   <resultMap id="WorkUser" type="Work">
       <result  property="name" column="wname"/>
       <collection property="users" ofType="User" javaType="ArrayList">
           <result property="id" column="uid" />
           <result property="name" column="uname" />
           <result property="wid" column="wid" />
       </collection>
   </resultMap>
</mapper>

测试:

@Test
public void selectWork(){
   SqlSession session = MybatisUtils.getSession();
   WorkMapper mapper = session.getMapper(WorkMapper.class);
   Work work = mapper.getWork(1);
   System.out.println(work.getName();
   System.out.println(work.getUsers();
}

2.按查询嵌套处理

<select id="getWork" resultMap="WorkUser">
select * from Work where id = #{id}
</select>
<resultMap id="WorkUser" type="Work">
   <!--column是一对多的外键 , 写的是一的主键的列名-->
   <collection property="users" javaType="ArrayList" ofType="User" column="id" select="getUser"/>
</resultMap>
<!--根据work表中的id再去查询user表中所对应的外键wid -->
<select id="getUser" resultType="User">
  select * from mybatis_test where wid = #{id}
</select>
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Mybatis可以通过association标签实现一对多查询。association标签用于处理一对一关系,而collection标签用于处理一对多关系。在一对多查询,通常会在主表包含一个外键,该外键指向从表的主键。 下面是一个简单的示例,假设我们有两个表Order和OrderItem,Order表包含一个外键指向OrderItem表的主键,代码如下: ``` <resultMap id="orderMap" type="Order"> <id property="orderId" column="order_id" /> <result property="orderName" column="order_name" /> <association property="orderItem" resultMap="orderItemMap" /> </resultMap> <resultMap id="orderItemMap" type="OrderItem"> <id property="orderItemId" column="order_item_id" /> <result property="orderItemName" column="order_item_name" /> </resultMap> <select id="selectOrder" resultMap="orderMap"> select * from order o left join order_item oi on o.order_id = oi.order_id where o.order_id = #{orderId} </select> ``` 在上面的示例,我们定义了两个resultMap,一个用于映射Order表,另一个用于映射OrderItem表。在Order表的resultMap,我们使用了association标签来处理一对多关系,将Order表的orderItem属性映射到OrderItem表,通过resultMap属性指定了OrderItem表的resultMap。 在select语句,我们通过left join关键字将Order表和OrderItem表关联起来,通过where条件指定了查询的订单ID。最终返回的结果将会是一个Order对象,其包含一个List<OrderItem>类型的orderItem属性,该属性包含了该订单对应的所有订单项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值