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

MyBatis 核心知识与实践

一、MyBatis 概述

1. 框架简介

        MyBatis 是一款支持自定义 SQL、存储过程以及高级映射的持久层框架。它避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作,使开发人员能够更专注于 SQL 语句的编写和业务逻辑的处理。

2. 核心组件

  • SqlSessionFactoryBuilder:用于创建 SqlSessionFactory 实例。
  • SqlSessionFactory:是 MyBatis 的核心对象,负责创建 SqlSession 实例。
  • SqlSession:提供了执行 SQL 语句、管理事务等功能。

3. 工作原理

        MyBatis 通过读取配置文件和映射文件,将 SQL 语句与 Java 方法进行映射。在运行时,根据方法调用生成相应的 SQL 语句,并执行数据库操作,最后将结果映射为 Java 对象返回。

二、MyBatis 基础操作

1. 环境搭建

  • 引入 MyBatis 依赖(以 Maven 项目为例):
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>x.x.x</version>
</dependency>
  • 配置mybatis-config.xml文件:
<?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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/EmpMapper.xml" />
        <mapper resource="mapper/DeptMapper.xml" />
    </mappers>
</configuration>

2. 单表操作

  • 实体类定义
public class Emp {
    private Integer empid;
    private String empname;
    private String empjob;
    private BigDecimal empsalary;
    private Integer empdid;

    // 省略getter和setter方法
}
  • Mapper 接口定义
public interface EmpDao {
    List<Emp> findAll();
    Emp findById(Integer id);
    int insert(Emp emp);
    int update(Emp emp);
    int delete(Integer id);
}
  • Mapper XML 文件配置
<?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 namespace="org.example.Dao.EmpDao">
    <resultMap id="BaseResultMap" type="Emp">
        <id property="empid" column="emp_id" jdbcType="INTEGER" />
        <result property="empname" column="emp_name" jdbcType="VARCHAR" />
        <result property="empjob" column="emp_job" jdbcType="VARCHAR" />
        <result property="empsalary" column="emp_salary" jdbcType="DECIMAL" />
        <result property="empdid" column="did" jdbcType="INTEGER" />
    </resultMap>

    <select id="findAll" resultMap="BaseResultMap">
        select * from tbl_emp
    </select>

    <select id="findById" resultMap="BaseResultMap">
        select * from tbl_emp where emp_id = #{id}
    </select>

    <insert id="insert" keyProperty="empid" useGeneratedKeys="true">
        insert into tbl_emp(emp_name, emp_job, emp_salary, did)
        values (#{empname}, #{empjob}, #{empsalary}, #{empdid})
    </insert>

    <update id="update">
        update tbl_emp
        set emp_name = #{empname}, emp_job = #{empjob}, emp_salary = #{empsalary}, did = #{empdid}
        where emp_id = #{empid}
    </update>

    <delete id="delete">
        delete from tbl_emp where emp_id = #{id}
    </delete>
</mapper>

3. 测试类编写

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.example.Entity.Emp;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class EmpDaoTest {

    @Test
    public void testFindAll() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        List<Emp> emps = empDao.findAll();
        for (Emp emp : emps) {
            System.out.println(emp);
        }

        sqlSession.close();
    }

    @Test
    public void testFindById() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        Emp emp = empDao.findById(1);
        System.out.println(emp);

        sqlSession.close();
    }

    @Test
    public void testInsert() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        Emp emp = new Emp();
        emp.setEmpname("张三");
        emp.setEmpjob("开发工程师");
        emp.setEmpsalary(new BigDecimal("8000"));
        emp.setEmpdid(1);
        int result = empDao.insert(emp);
        System.out.println("插入成功,影响行数:" + result);

        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void testUpdate() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        Emp emp = new Emp();
        emp.setEmpid(1);
        emp.setEmpname("李四");
        emp.setEmpjob("高级开发工程师");
        emp.setEmpsalary(new BigDecimal("10000"));
        emp.setEmpdid(2);
        int result = empDao.update(emp);
        System.out.println("更新成功,影响行数:" + result);

        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void testDelete() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        int result = empDao.delete(1);
        System.out.println("删除成功,影响行数:" + result);

        sqlSession.commit();
        sqlSession.close();
    }
}

三、MyBatis 高级特性

1. 分页查询

  • 引入 PageHelper 依赖
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>6.0.0</version>
</dependency>
  • 在 MyBatis 配置文件中添加插件配置
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 可配置参数 -->
        <property name="param1" value="value1" />
    </plugin>
</plugins>
  • 代码示例
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.example.Dao.EmpDao;
import org.example.Entity.Emp;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class PaginationTest {

    @Test
    public void testPagination() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        EmpDao empDao = sqlSession.getMapper(EmpDao.class);

        // 开启分页,查询第一页,每页显示3条数据
        PageHelper.startPage(1, 3);
        List<Emp> emps = empDao.findAll();

        // 将查询结果封装到PageInfo中
        PageInfo<Emp> pageInfo = new PageInfo<>(emps);

        // 输出相关信息
        System.out.println("总条数:" + pageInfo.getTotal());
        System.out.println("总页数:" + pageInfo.getPages());
        System.out.println("当前页记录:");
        List<Emp> list = pageInfo.getList();
        for (Emp emp : list) {
            System.out.println(emp);
        }

        sqlSession.close();
    }
}

2. 联表查询

  • 多对一关系查询(以员工和部门为例)
  • 使用association标签
<?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 namespace="org.example.Dao.EmpDao">
    <resultMap id="EmpWithDeptResultMap" type="Emp">
        <id property="empid" column="emp_id" jdbcType="INTEGER" />
        <result property="empname" column="emp_name" jdbcType="VARCHAR" />
        <result property="empjob" column="emp_job" jdbcType="VARCHAR" />
        <result property="empsalary" column="emp_salary" jdbcType="DECIMAL" />
        <result property="empdid" column="did" jdbcType="INTEGER" />
        <association property="dept" javaType="Dept">
            <id property="deptid" column="dept_id" jdbcType="INTEGER" />
            <result property="deptname" column="dept_name" jdbcType="VARCHAR" />
            <result property="deptloc" column="dept_loc" jdbcType="VARCHAR" />
        </association>
    </resultMap>

    <select id="findAllWithDept" resultMap="EmpWithDeptResultMap">
        select e.*, d.dept_id, d.dept_name, d.dept_loc
        from tbl_emp e
        join tbl_dept d on e.did = d.dept_id
    </select>
</mapper>
  • 一对多关系查询(以部门和员工为例)
  • 使用collection标签
<?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 namespace="org.example.Dao.DeptDao">
    <resultMap id="DeptWithEmpsResultMap" type="Dept">
        <id property="deptid" column="dept_id" jdbcType="INTEGER" />
        <result property="deptname" column="dept_name" jdbcType="VARCHAR" />
        <result property="deptloc" column="dept_loc" jdbcType="VARCHAR" />
        <collection property="emps" ofType="Emp">
            <id property="empid" column="emp_id" jdbcType="INTEGER" />
            <result property="empname" column="emp_name" jdbcType="VARCHAR" />
            <result property="empjob" column="emp_job" jdbcType="VARCHAR" />
            <result property="empsalary" column="emp_salary" jdbcType="DECIMAL" />
            <result property="empdid" column="did" jdbcType="INTEGER" />
        </collection>
    </resultMap>

    <select id="findAllWithEmps" resultMap="DeptWithEmpsResultMap">
        select d.*, e.*
        from tbl_dept d
        left join tbl_emp e on d.dept_id = e.did
    </select>
</mapper>

3. 动态 SQL

<trim>:通过修剪 SQL 语句的开头和结尾来动态生成 SQL 片段。它可以用于去除不必要的 SQL 关键字或条件语句,并提供了一些属性来定义修剪规则。

<where>:用于在生成的 SQL 语句中添加 WHERE 子句。它可以自动处理条件语句的前缀,并在有条件语句存在时添加 WHERE 关键字。而且会去除sql的第一个and标签。

<set>:用于在生成的 SQL 语句中添加 SET 子句。它主要用于更新操作,可以根据条件来动态生成需要更新的列。

<foreach>:用于在生成的 SQL 语句中进行循环操作。它可以遍历集合或数组,并根据指定的模板将集合元素或数组元素插入到 SQL 语句中。

<if>:用于在生成的 SQL 语句中添加条件判断。可以根据指定的条件决定是否包含某个 SQL 语句片段。

<choose>:类似于 Java 中的 switch 语句,根据条件选择执行不同的 SQL 语句片段。它可以包含多个 <when> 和一个可选的 <otherwise> 标签。

<when>:用于在 <choose> 标签中定义条件分支。可以根据指定的条件判断是否执行特定的 SQL 语句片段。

<otherwise>:在 <choose> 标签中可选的标签,用于定义当没有任何 <when> 条件匹配时执行的 SQL 语句片段。

  • if标签示例(根据条件查询员工)
<?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 namespace="org.example.Dao.EmpDao">
    <select id="selectByCondition" resultMap="BaseResultMap">
        select * from tbl_emp
        <where>
            <if test="name!= null and name!= ''">
                and emp_name like concat('%', #{name}, '%')
            </if>
            <if test="job!= null and job!= ''">
                and emp_job = #{job}
            </if>
            <if test="salary!= null">
                and emp_salary = #{salary}
            </if>
        </where>
    </select>
</mapper>
  • choosewhenotherwise标签示例(根据条件查询员工)
<?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 namespace="org.example.Dao.EmpDao">
    <select id="selectByCondition2" resultMap="BaseResultMap">
        select * from tbl_emp
        <where>
            <choose>
                <when test="name!= null and name!= ''">
                    and emp_name like concat('%', #{name}, '%')
                </when>
                <when test="job!= null and job!= ''">
                    and emp_job = #{job}
                </when>
                <when test="salary!= null">
                    and emp_salary = #{salary}
                </when>
                <otherwise>
                    and 1 = 1
                </otherwise>
            </choose>
        </where>
    </select>
</mapper>
  • foreach标签示例(批量删除员工)
<?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 namespace="org.example.Dao.EmpDao">
    <delete id="batchDelete">
        delete from tbl_emp where emp_id in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>
</mapper>


http://www.kler.cn/a/441790.html

相关文章:

  • AndroidStudio——安卓项目结构与文件介绍
  • ubuntu+ros新手笔记(二):古月·ROS2入门21讲学习笔记
  • 【PostgreSQL异常解决】PostgreSQL 异常错误: PG::Error 服务意外关闭连接
  • 【ArcGIS技巧】天地图下载瓦片并合并成图片
  • Hive-4.0.1数据库搭建(可选配置用户名密码远程连接,涵盖切换为tez引擎)
  • FFmpeg 4.3 音视频-多路H265监控录放C++开发二十一.3,RTCP协议, RTCP协议概述,RTCP协议详情
  • 图数据库 | 15、可扩展的图数据库设计(上)
  • C# 读取EXCEL的数据批量插入单个PDF里的多个位置
  • 系统可观测性——Logback日志框架
  • Spring Boot 3.x:自动配置类加载机制的变化
  • 如何在Linux上搭建DHCP服务
  • 解决Docker拉取镜像报错问题的详细步骤
  • win10配置子系统Ubuntu子系统(无需通过Windows应用市场)实际操作记录
  • Python中构建全局字典的详细指南
  • docker快速实现ELK的安装和使用
  • Centos gcc 12.3 安装
  • 使用CNN模型训练图片识别(键盘,椅子,眼镜,水杯,鼠标)
  • docker 拉取镜像 | 创建容器 | 容器运行
  • k8s,理解容器中namespace和cgroups的原理
  • Android Scratch分区