MyBatis学习笔记:进阶知识2

ops/2024/12/15 11:47:22/

MyBatis 作为一款优秀的持久层框架,在 Java 开发中占据着重要地位。它简化了数据库操作,提供了灵活且高效的数据访问方式。本文将深入探讨 MyBatis 的核心功能,包括分页查询、联表查询、动态 SQL 以及代码自动生成,并结合实际案例进行详细分析,帮助读者更好地理解和应用这些功能。

一、MyBatis 框架回顾

在深入学习 MyBatis 的高级特性之前,我们先来回顾一下 MyBatis 框架的基础知识。MyBatis 框架主要用于数据库访问,它通过将 SQL 语句与 Java 代码分离,实现了数据持久化层的解耦。以下是 MyBatis 框架的一些关键知识点:

(一)注解方式实现单表操作

MyBatis 提供了一系列注解,如@Select@Insert@Delete@Update,用于在接口方法上直接编写 SQL 语句,实现对单表的增删改查操作。这种方式简单直观,适用于简单的数据库操作场景。

(二)MyBatis 的优化策略

  1. 日志添加
    • 引入log4jjar包,并添加log4j.properties配置文件,以便在开发过程中更好地跟踪和调试 MyBatis 的执行过程,帮助开发者快速定位问题。
  2. 实体类别名设置
    • 为实体类起别名,在编写 SQL 语句时可以直接使用别名代替完整的类名,使 SQL 语句更加简洁易读,提高代码的可维护性。
  3. 数据源信息抽取
    • 将数据源的信息抽取到属性文件中,通过${key}的方式引用属性值。这样,在切换数据源或修改数据库连接信息时,无需修改代码,只需调整属性文件即可,增强了程序的灵活性和可配置性。

(三)其他常用功能

  1. 获取递增 ID 值
    • 在执行插入操作时,通过设置<insert useGeneratorKey="true" keyProperty="属性">,可以方便地获取数据库自动生成的递增 ID 值,并将其赋值给实体类的相应属性。
  2. 多参处理
    • 使用@Param("名称")注解为方法参数命名,然后在 SQL 语句中通过#{名称}引用参数,解决了多参数传递的问题,使 SQL 语句与方法参数的对应关系更加清晰。
  3. 特殊符号处理
    • 当 SQL 语句中包含特殊符号时,可以使用转义符或者<![CDATA[sql]]>的方式进行处理,避免因特殊符号导致的 SQL 语法错误。
  4. 模糊查询实现
    • 通过concat("%",#{},"%")函数,在查询条件中实现模糊查询,方便根据关键字搜索相关数据。
  5. 属性名与列名不一致处理
    • 提供了两种解决方案。一是为查询的列起别名,使其与属性名一致;二是通过ResultMap标签建立列名和属性名的映射关系,确保数据的正确封装。

二、分页查询

在实际应用中,分页查询是常见的需求。MyBatis 本身没有提供分页功能,但可以通过集成分页插件来实现。以 PageHelper 插件为例,详细介绍分页查询的实现步骤。

(一)引入 PageHelper 依赖

在项目的pom.xml文件中添加 PageHelper 的依赖:

<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>6.0.0</version>
</dependency>

(二)配置 MyBatis

在 MyBatis 的配置文件中,添加如下插件配置:

<plugins><!-- com.github.pagehelper为PageHelper类所在包名 --><plugin interceptor="com.github.pagehelper.PageInterceptor"><property name="param1" value="value1"/></plugin>
</plugins>
<select id="selectAll" resultType="java.util.Map">select * from tbl_emp e join tbl_dept d on e.did = d.dept_id
</select>

  1. 使用 association 标签(第二种方案)
    • 优点:通过定义实体类之间的关联关系,使代码结构更加清晰,属性调用更加直观。
    • 缺点:需要创建额外的实体类和映射配置。
    • 示例代码:
java">public List<Emp> selectAll01();
<resultMap id="EmpMapper" type="org.example.entity.Emp"><id column="emp_id" property="id"/><result column="emp_name" property="name"/><result column="emp_job" property="job"/><result column="emp_salary" property="salary"/><result column="did" property="di"/><!-- association:表示多对一的标签 property: 该类中实体类的属性名 javaType:该属性所属于的类型 --><association property="dept" javaType="org.example.entity.Dept"><id column="dept_id" property="id"/><result column="dept_name" property="name"/><result column="dept_loc" property="loc"/></association>
</resultMap>
<select id="selectAll01" resultMap="EmpMapper">select * from tbl_emp e join tbl_dept d on e.did = d.dept_id
</select>

(二)一对多关系查询

  1. 使用 Map 类(第一种方案,省略)

    • 与多对一关系中使用 Map 集合类类似,但在一对多场景下,使用 Map 可能会导致数据结构不够清晰,维护困难。
  2. 使用 Collection 标签(第二种方案)

    • 优点:能够清晰地表达一对多的关系,通过配置Collection标签,可以方便地获取关联的多个对象集合。
    • 缺点:配置相对复杂,需要仔细定义映射关系。
    • 示例代码(查询部门信息并携带部门对应的员工信息):
java">public Dept selectById(int id);
public List<Dept> selectAll();
<resultMap id="DeptMapper" type="org.example.entity.Dept"><id column="dept_id" property="id" /><result column="dept_name" property="name"/><result column="dept_loc" property="loc"/><!-- collection:表示一对多的标签 property:集合对应的属性名 ofType:该属性集合的泛型类型 --><collection property="emp" ofType="org.example.entity.Emp"><id column="emp_id" property="id"/><result column="emp_name" property="name"/><result column="emp_job" property="job"/><result column="emp_salary" property="salary"/><result column="did" property="did"/></collection>
</resultMap>
<select id="selectById" resultMap="DeptMapper">select * from tbl_emp e join tbl_dept d on e.did = d.dept_id where dept_id = #{id}
</select>
<select id="selectAll" resultMap="DeptMapper">select * from tbl_emp e join tbl_dept d on e.did = d.dept_id
</select>

(三)联表查询的 SQL 优化

  1. 合理选择连接方式
    • 根据业务需求和数据特点,选择合适的连接方式(如INNER JOINLEFT JOINRIGHT JOIN),避免不必要的数据冗余和查询性能问题。
  2. 建立合适的索引
    • 对关联字段建立索引,可以提高联表查询的效率。例如,在员工表的did字段和部门表的dept_id字段上建立索引。

四、动态 SQL 标签

在实际应用中,查询条件往往是动态变化的。MyBatis 提供了动态 SQL 标签,用于根据不同的条件动态拼接 SQL 语句,提高代码的灵活性和可维护性。

(一)动态 SQL 标签介绍

  1. <trim>标签
    • 通过修剪 SQL 语句的开头和结尾来动态生成 SQL 片段。可以去除不必要的 SQL 关键字或条件语句,并根据属性定义修剪规则。
  2. <where>标签
    • 用于在生成的 SQL 语句中添加WHERE子句。它能自动处理条件语句的前缀,在有条件语句存在时添加WHERE关键字,并去除 SQL 中的第一个AND标签。
  3. <set>标签
    • 用于在生成的 SQL 语句中添加SET子句,主要用于更新操作,根据条件动态生成需要更新的列。
  4. <foreach>标签
    • 用于在 SQL 语句中进行循环操作,可遍历集合或数组,并根据指定模板将元素插入到 SQL 语句中,常用于批量删除和批量添加操作。
  5. <if>标签
    • 根据指定条件决定是否包含某个 SQL 语句片段,实现条件判断。
  6. <choose><when><otherwise>标签
    • 类似于 Java 中的switch语句,<choose>根据条件选择执行不同的 SQL 语句片段,<when>定义条件分支,<otherwise>在所有<when>条件不匹配时执行的 SQL 语句片段。

(二)示例代码

  1. 使用<if>标签实现多条件查询
java">public List<Emp> selectByCondition01(@Param("name") String name, @Param("job") String job, @Param("salary") Double salary);
<select id="selectByCondition01" resultMap="EmpMapper">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>
  1. 使用<choose><when><otherwise>标签实现条件分支查询
<select id="selectByCondition02" resultMap="EmpMapper">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></choose></where>
</select>
  1. 使用<foreach>标签实现批量删除和批量添加
    • 批量删除示例:
java">public int batchDelete(@Param("ids") Integer[] ids);
<delete id="batchDelete">delete from tbl_emp where id in<foreach collection="ids" item="i" open="(" close=")" separator=", ">#{id}</foreach>
</delete>
  • 批量添加示例:
java">public int batchInsert(@Param("emps") List<Emp> emps);
<insert id="batchInsert">insert into tbl_emp(emp_name,emp_job,emp_salary,did) values<foreach collection="emps" item="e" separator=",">(#{e.name},#{e.job},#{e.salary},#{e.did})</foreach>
</insert>

(三)动态 SQL 的应用场景

  1. 多条件组合查询
    • 根据用户输入的不同查询条件,动态生成包含相应条件的 SQL 语句,如电商平台中的商品搜索功能,根据品牌、价格范围、规格等多个条件进行筛选查询。
  2. 动态更新操作
    • 根据业务规则,只更新部分字段。例如,用户信息修改功能,仅更新用户修改的字段,而不是全部字段。
  3. 批量操作
    • 如批量删除选中的记录或批量插入多条数据,提高操作效率,减少数据库交互次数。

五、MyBatis 代码自动生成

随着项目的不断发展,编写大量的 MyBatis 映射文件和实体类会变得繁琐且容易出错。MyBatis 提供了代码自动生成工具,可以根据数据库表结构快速生成实体类、映射文件和 DAO 接口等代码,提高开发效率。

(一)使用 MyBatis Generator 工具

  1. 配置文件编写
    • 创建一个generatorConfig.xml配置文件,指定数据库连接信息、生成代码的目标路径、实体类包名、映射文件包名等参数。例如:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration><context id="DB2Tables" targetRuntime="MyBatis3"><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC"userId="root"password="123456"></jdbcConnection><javaModelGenerator targetPackage="com.example.entity" targetProject="src/main/java"><property name="enableSubPackages" value="true"/><property name="trimStrings" value="true"/></javaModelGenerator><sqlMapGenerator targetPackage="com.example.mapper" targetProject="src/main/resources"><property name="enableSubPackages" value="true"/></sqlMapGenerator><javaClientGenerator type="XMLMAPPER" targetPackage="com.example.dao" targetProject="src/main/java"><property name="enableSubPackages" value="true"/></javaClientGenerator><table tableName="tbl_emp" domainObjectName="Emp"/><table tableName="tbl_dept" domainObjectName="Dept"/></context>
</generatorConfiguration>
  1. 执行生成命令
    • 在命令行中执行 MyBatis Generator 的命令,或者在项目中通过 Maven 插件执行。执行后,将根据配置生成相应的实体类、映射文件和 DAO 接口。

(二)代码生成器的优势与注意事项

  1. 优势
    • 大大提高开发效率,减少手动编写代码的工作量,降低出错率。
    • 保证代码结构的一致性,便于团队协作和项目维护。
  2. 注意事项
    • 生成的代码可能需要根据实际需求进行适当调整,如添加自定义的方法、修改注释等。
    • 当数据库表结构发生变化时,需要及时重新生成代码,以确保代码与数据库的一致性。

http://www.ppmy.cn/ops/142093.html

相关文章

批量DWG文件转换低版本(CAD图转低版本)——c#插件实现

此插件可实现指定路径下所有dwg文件&#xff08;包含子文件夹内dwg&#xff09;一键全部转为低版本&#xff08;包含2004、2007、2018版本&#xff0c;也可定制指定版本&#xff09;。效果如下&#xff1a; &#xff08;使用方法&#xff1a;命令行输入 “netload” 加载插件&…

latex设置引用顺序

在 LaTeX 中&#xff0c;引用的顺序通常是由所选择的 参考文献样式&#xff08;bibliographystyle&#xff09; 决定的。如果你希望根据引用的顺序排列参考文献&#xff0c;可以选择合适的参考文献样式&#xff0c;并按照以下步骤进行设置。 常见的几种引用顺序设置方式有&…

小程序开发常见问题

一、开发方案选择 1.小程序原生开发&#xff1a;需要live-player组件资质&#xff0c;对开发者的资质要求较高&#xff0c;开发难度较大&#xff1b; 2.小程序内嵌H5&#xff1a;因校验文档上限&#xff0c;目前平台已经不支持配置校验文件&#xff1b; 3.半屏小程序&#xff1…

MATLAB 平面线段与线段求交点(100)

MATLAB 平面线段与线段求交点(100) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 计算平面上,两线段是否相交,若相交计算交点坐标 二、算法实现 1.代码 代码如下(示例): % 示例用法 % 定义两条线段的端点 p0 = [1, 2]; % 线段1的第一个点

Scala特殊符号使用大全2

/&#xff1a;用于定义除法操作符。 val x 10 val y 5 val z x / y // 结果为 2 %&#xff1a;用于定义模操作符。 val x 10 val y 3 val z x % y // 结果为 1 :&#xff1a;用于列表的头元素。 val list 1 :: 2 :: 3 :: Nil // 结果为 List(1, 2, 3) :::&…

Golang中的go.mod和go.sum

Golang中的go.mod和go.sum 在Go语言中&#xff0c;go.mod和go.sum是两个至关重要的文件&#xff0c;它们共同构成了Go Modules系统的核心&#xff0c;用于管理和跟踪项目的依赖关系。 go.mod 作用&#xff1a; 定义模块名称&#xff1a;go.mod文件的第一行通常是module关键字…

电商项目-微服务网关鉴权JWT

一 、什么是微服务鉴权 当有了网关,用户所有的请求都会经过网关&#xff0c;然后由网关将用户请求&#xff0c;转发到具体某个服务。网关相当于后端服务的统一入口&#xff0c;所以现在非常方便的可以在网关系统中进行相关服务的权限校验。 鉴权就是鉴定有没有访问的权限。如果…

购物车案例--分模块存储数据,发送请求数据渲染,底部总计数量和价格

shift鼠标右键&#xff0c;打开powershell&#xff0c;新建项目 自定义 只有一个页面&#xff0c;不涉及路由&#xff0c;勾选vuex,css,babel 无需保存预设 回车项目开始创建 项目用vscode打开 将src里的内容全部清空 将第七天的课程准备代码复制粘贴到src中 刷新页面&…