当前位置: 首页 > news >正文

mybatis多表查询

一对一、一对多、多对一、多对多

首先需要明确的是,无论是一对一还是一对多,都有三种方法,且思路一致,唯一有变化的是极个别的关键字,所以我们以一对一为例进行多表查询操作的详细了解,同时采用xml文件的形式进行多表查询而不采用注解的形式。

首先,在利用mybatis进行多表查询前,需要先熟悉mysql的多表查询操作分为以下三大类:

1.连接查询(自然连接,笛卡尔积形式的连接,左外连接,右外连接,内连接)——将两个表通过对应外键关系进行连接,横向拼接,后再去查找

2.子查询(先查询一个表当中某个属性列,作为参数再给另一个表查询)

3.联合查询(纵向拼接)一般不怎么用

而mybatis当中的三种查询本质上就都对应了前两种

方法一、

最为简单(不推荐使用)

将两个表直接合并为一个类

Person表:

IdCard表

package com.mybatis.entity;

import lombok.Data;

@Data
public class PersonAndIdCard {
    private Integer pid;
  
    private String pname;

    private String tel;

    private String sex;

    private Integer cid;

    private String cnum;
}

mapper接口:

既可以写在IDcard的对应mapper接口下,也可以写在people对应的mapper接口下,以写在people对应的mapper接口下为例

List<PersonAndIdCard> findPersonAndIdCard(String pname);

xml映射文件:

id对应的是mapper接口当中定义抽象方法,由mybatis自动补齐。parameterType是输入参数类型,可以不用写。resultType为返回类型,也就是我们需要去映射到的类,这个必须写。此处采用的是自动映射,需要注意的是,当mysql当中的属性名称和java当中实体类的属性名称不相同时,必须采用手动映射!

 <select id="findPersonAndIdCard" parameterType="string" resultType="com.mybatis.entity.PersonAndIdCard">
        select * from person p,idcard i where p.cid=i.cid and p.pname=#{pname}
    </select>

当然当数据库种属性名为下划线命名法时,可以引入下划线转小驼峰的配置,就可以不用手动映射了。方法如下:

在mybatis的总配置文件下mybatis-config.xml

设置

<settings>
    <!-- 启用驼峰命名转换 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

这样的话,就可以自动实现mysql数据库下划线字段到类小驼峰属性的自动映射,但是在使用sql语句访问数据库时,仍然要使用原数据库字段名称,而不是使用下划线。

该方法查询本质上就是通过多表的连接查询,将两个表笛卡尔积的形式连接一起,在通过条件判断返回查询结果。我们可以采用左外连接或右外连接的方式来提高执行速度

方法二、

不将两个表新建类合并,而是将其中一个类写入另一个当中,以写入person类为例:

package com.mybatis.entity;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * 
 * @TableName person
 */
@Data
public class Person implements Serializable {
 
    private Integer pid;

    private String pname;

    private String tel;
 
    private String sex;

   private Idcard idcard;

}
 List<Person> findPersonAndIdCard2(String pname);

 此时便采用手动映射,column为mysql对应的字段名,字段名要完全和mysql一致,property为对应的java实体类的属性名,同时本质上依然是连接查询,我们同样可以改写为左外连接的方式来简化sql执行速度。手动映射association标签当种,javaType为被映射的类的全部地址名称(由于我在总配置文件中对该地址起了别名,所以可以直接写Idcard),即将查询到的字段映射到Idcard类。property则将该类输送给Person当中的内置类Idcard,为其赋值。

 <resultMap id="resultMap1" type="person">
        <id property="pid" column="pid"/>
        <result property="pname" column="pname" />
        <result property="tel" column="tel" />
        <result property="sex" column="sex" />
        <association property="idcard" javaType="Idcard">
            <id property="cid" column="cid"/>
            <result property="cnum" column="cnum"/>
        </association>
    </resultMap>
    <select id="findPersonAndIdCard2" resultMap="resultMap1">
        select * from person p,idcard i where p.cid=i.cid and p.pname=#{pname}
    </select>

方法三、

该方法本质上是子查询

Person类和第二种方法相同

mapper接口也和第二种方法相同

   List<Person> findPersonAndIdCard3(String pname);

 实现类如下:

先根据pname查询person表,在将查询到的结果当中的索引cid传输给select属性当中的selectbyprimarykey方法,在将selectbyprimarykey查询到的结果映射到idcard

    <resultMap id="resultMap2" type="person">
        <id property="pid" column="pid"/>
        <result property="pname" column="pname"/>
        <result property="tel" column="tel"/>
        <result property="sex" column="sex"/>
        <association property="idcard" select="com.mybatis.mapper.IdcardMapper.selectByPrimaryKey" column="cid"/>
    </resultMap>
    <select id="findPersonAndIdCard3" resultMap="resultMap2">
        select * from person where pname=#{pname}
    </select>
   <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from idcard
        where  cid = #{cid} 
    </select>

这就本质上是子查询,也是嵌套查询,先查询出结果,再由这个结果当中的一些值去再深度查找对应的其他值。

举一个其他的查询实战:

package com.mybatis.entity;

import java.util.Date;
import lombok.Data;

/**
 * 
 * @TableName employee
 */
@Data
public class Employee {
    private Integer eId;
    private String eName;
    private Integer age;
    private String position;
    private Department department;
    private Integer salary;
    private Date hireData;
}

 

public class Test {
    public static void main(String[] args) {
        String name="%张%";
        String dname="信息部";
//        String position="经理";
        Integer minsalary=2000;
        Integer maxSalary=30000;
        HashMap<String, Object> hashMap=new HashMap<>();
        hashMap.put("name",name);
        hashMap.put("dname",dname);
//        hashMap.put("position",position);
        hashMap.put("minsalary",minsalary);
        hashMap.put("maxsalary",maxSalary);
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        PageHelper.startPage(1,3);
        List<Employee> empMoreOrderLikePage = mapper.findEmpMoreOrderLikePage(hashMap);
        empMoreOrderLikePage.forEach(System.out::println);
        MybatisUtil.closeSqlSession(sqlSession);
    }
}
List<Employee> findEmpMoreOrderLikePage(HashMap<String,Object> hashMap);
   <resultMap id="resultMap" type="com.mybatis.entity.Employee">
        <id property="eId" column="e_id"/>
        <result property="eName" column="e_name"/>
        <result property="age" column="age"/>
        <result property="position" column="position"/>
        <result property="salary" column="salary"/>
        <result property="hireData" column="hire_data"/>
        <association property="department" javaType="com.mybatis.entity.Department">
            <id property="dId" column="d_id"/>
            <result property="dName" column="d_name"/>
            <result property="location" column="location"/>
        </association>
    </resultMap>
    <select id="findEmpMoreOrderLikePage" resultMap="resultMap">
        select * from employee e left join department d on e.d_id=d.d_id
        <where>
            <if test="name != null">
                e.e_name Like #{name}
            </if>
            <if test="position!=null">
                and e.position=#{position}
            </if>
            <if test="dname!=null">
                 and d.d_name=#{dname}
            </if>
            <if test="min_salary!=null">
                 <if test="max_salary!=null">
                and e.salary between #{min_salary} and #{}
                 </if>
            </if>

        </where>
        ORDER BY e.salary DESC
    </select>

总结:

1.接口中参数一般只能是一个,当为多个时,就不能通过#{属性名}获取了需要以下几种方法处理

      1).#{param1},#{param2}……来处理

      2).#{arg0},#{arg1}……来处理

       3)最常用:通过hashmap来传递值,同时后面的动态sql也可以直接通过键值对当中的键名来判断是否有该参数。

        4)传递实体类,同样可以通过属性名直接获取

2.此处用的是方法二,进行左外连接后查询。

要想使用方法三,需要做出如下处理:

1.通过部门名先查询到pid

2.根据查询到的pid和传过来的参数再来进行查询

 可以参考下面的例子自行去写

<resultMap id="resultMap4" type="person">
    <id property="pid" column="pid"/>
    <result property="pname" column="pname"/>
    <collection 
        property="bankcardList" 
        select="com.mybatis.mapper.BankcardMapper.selectByPidAndBalance"
        column="{pid=pid, minBalance=minBalance}"/>  <!-- pid 来自主查询字段,minBalance 来自 HashMap -->
</resultMap>

<select id="findPersonAndIdCard5" resultMap="resultMap4">
    SELECT pid, pname 
    FROM person 
    WHERE pname = #{pname}  <!-- #{pname} 从 HashMap 中获取 -->
</select>

column必须用{}的形式来接受 

// BankcardMapper.java
List<Bankcard> selectByPidAndBalance(
    @Param("pid") Integer pid, 
    @Param("minBalance") BigDecimal minBalance
);

此处必须要@param来注解,多参传过来时必须用 

Map<String, Object> params = new HashMap<>();
params.put("pname", "张三"); 
params.put("minBalance", new BigDecimal("1000.00"));  // 传递给子查询的参数

List<Person> persons = personMapper.findPersonAndIdCard5(params);
SELECT * FROM bankcard 
WHERE pid = 123  -- 主查询返回的 pid
  AND balance >= 1000.00;  -- 来自 HashMap 的 minBalance

相关文章:

  • Python实例题:Python实现iavaweb项目远端自动化更新部署
  • 解决双系统ubuntu24.04开机出现花屏等情况
  • Java面试黄金宝典48
  • Java 多线程编程之原子类 AtomicBoolean(构造方法、获取与设置、比较并设置)
  • rancher 解决拉取dashboard-shell镜像失败的问题
  • Wincc管对象的使用
  • 【ESP32-microros(vscode-Platformio)】
  • Go 语言中的 package main、 func main() 和main.go的使用规范
  • 浮点数比较在Eigen数学库中的处理方法
  • AI前沿周报:2025年3月技术深度解析
  • Express中间件(Middleware)详解:从零开始掌握(1)
  • 在Java项目中,引入【全局异常处理器】
  • HarmonyOS-ArkUI V2装饰器-@Once
  • 第一节:React 基础篇-React虚拟DOM原理及Diff算法优化策略
  • 【Web功能测试】注册与登录功能测试用例设计深度解析
  • (十四)安卓开发中的RecyclerView详解
  • Python 和 JavaScript两种语言的相似部分-由DeepSeek产生
  • 计算机操作系统-【死锁】
  • 信奥赛之c++基础(循环结构之for循环)
  • Java常用工具算法-6--秘钥托管云服务3--微软zure Key Vault
  • 买好域名之后怎么做网站/珠海优化seo
  • 哪些网站可以做招生/网上营销方式和方法
  • 网站seo测评/西部数码域名注册
  • 做网站分层技术/网络推广公司哪里好
  • 导游网站如何建设的/百度seo排名优化排行
  • 做网站怎么查看来访ip/微博推广