一、MyBatis 基础概念相关

news2024/12/20 21:29:16

一、MyBatis 基础概念相关

  1. 什么是 MyBatis?
    MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作,使得开发人员能够更专注于 SQL 语句本身以及业务逻辑,通过简单的 XML 配置文件或者注解就能将 Java 对象与数据库表中的记录进行映射关联。

  2. MyBatis 与 JDBC 的区别是什么?

    • 代码复杂度方面:JDBC 操作数据库时需要编写大量的样板代码,比如加载驱动、创建连接、编写 SQL 语句、设置参数、执行语句、处理结果集以及关闭资源等一系列繁琐操作。而 MyBatis 对 JDBC 进行了封装,极大地简化了这些流程,开发人员只需关注 SQL 语句编写和对象与数据库记录的映射关系,很多底层操作都由 MyBatis 自动完成。
    • 数据库移植性方面:JDBC 是 Java 操作数据库的标准接口,理论上可以切换不同的数据库,但在实际切换时,由于不同数据库的 SQL 语法差异等,需要大量修改 SQL 语句。MyBatis 可以通过配置数据库连接信息方便地切换数据库,并且能针对不同数据库进行 SQL 语句的差异化配置,一定程度上提高了数据库移植的便利性。
    • 数据映射灵活性方面:JDBC 处理查询结果集时,通常需要手动将结果集中的数据逐行提取并封装到 Java 对象中,比较麻烦。MyBatis 提供了强大的映射功能,比如通过 resultMap 可以灵活地将数据库表的列与 Java 对象的属性进行各种复杂的映射,支持一对一、一对多、多对多等关系映射。
  3. 简述 MyBatis 的工作原理。

    • 加载配置文件:MyBatis 首先会加载全局配置文件(通常是 mybatis-config.xml),这个文件包含了数据库连接相关的配置(如驱动类、连接地址、用户名、密码等)以及其他诸如类型别名、插件、映射器(mapper)等全局设置信息。
    • 构建 SqlSessionFactory:根据加载的配置文件,创建 SqlSessionFactory 对象,它是线程安全的,整个应用程序生命周期内一般只需创建一次,是后续创建 SqlSession 的工厂类。
    • 获取 SqlSession:从 SqlSessionFactory 中获取 SqlSession 对象,SqlSession 相当于数据库连接会话,提供了执行查询、插入、更新、删除等操作的方法,但它不是线程安全的,通常在每次需要与数据库交互时获取,用完后及时关闭。
    • 查找映射语句(Mapper):当要执行具体数据库操作时,依据接口(通常是 Mapper 接口)和对应的 XML 映射文件(或基于注解的映射方式)去查找对应的 SQL 语句定义。
    • 执行 SQL 语句:通过 SqlSession 调用对应的 Mapper 接口方法,底层会根据映射找到对应的 SQL 语句去执行,对于查询操作会按照配置的结果映射规则(如 resultMap)将结果转换为对应的 Java 对象返回。
    • 处理结果:根据操作类型(查询、更新等)对返回结果进行相应处理,比如查询操作得到结果后按规则映射为 Java 对象或集合,更新操作返回受影响行数等信息。
    • 关闭 SqlSession:完成数据库交互后,关闭 SqlSession 释放资源。

二、配置文件相关

  1. 请介绍一下 MyBatis 的配置文件(mybatis-config.xml)主要包含哪些内容?

    • 环境配置(environments):可以配置多个数据库环境(如开发环境、测试环境、生产环境等),每个环境下定义事务管理器(transactionManager)类型(通常是 JDBC 或 MANAGED)以及数据源(dataSource)类型(如 POOLEDUNPOOLEDJNDI 等),并配置相应的数据库连接详细信息,像驱动、连接地址、用户名、密码等。
    • 类型别名(typeAliases):为 Java 类型定义别名,方便在映射文件等地方使用,减少全限定类名的书写,例如可以定义 typeAliases 下的 <typeAlias alias="User" type="com.example.entity.User"/>,后续在 SQL 映射等地方就可以直接用 User 来指代 com.example.entity.User 这个类了。
    • 插件(plugins):可以配置插件来增强 MyBatis 的功能,比如分页插件、性能监控插件等,插件可以拦截 MyBatis 执行过程中的某些方法,实现自定义的逻辑,像在执行查询语句前添加分页逻辑等。
    • 映射器(mappers):用于指定 SQL 映射文件(.xml 文件)或者 Mapper 接口的位置,让 MyBatis 能够找到对应的 SQL 语句定义,常见的配置方式有通过 <mapper resource="com/example/mapper/UserMapper.xml"/> 来指定 XML 文件路径,或者 <mapper class="com.example.mapper.UserMapper"/> 直接指定接口类(一般基于注解的映射方式下会这样用)。
  2. 如何在 MyBatis 配置文件中配置多数据源?
    可以在 environments 标签内配置多个 <environment> 子标签,每个子标签代表一个不同的数据库环境,设置不同的 idtransactionManager 和 dataSource 等信息,例如:

<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/mydb?useSSL=false"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </dataSource>
    </environment>
    <environment id="test">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/testdb?useSSL=false"/>
            <property name="username" value="root"/>
            <property name="password" value="654321"/>
        </dataSource>
    </environment>
</environments>


然后在获取 SqlSessionFactory 时,可以通过指定不同的环境 id 来选择使用对应的数据源,例

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "test"); // 这里选择使用 "test" 环境对应的数据源

三、SQL 映射相关

  1. MyBatis 的 SQL 映射文件(.xml 文件)中常见的标签有哪些,分别有什么作用?
    • <select>:用于定义查询语句,通过 id 属性来唯一标识该查询语句,在 Mapper 接口中会有对应的方法与之关联,resultMap 或 resultType 属性用于指定查询结果的映射方式,可以返回单个对象、对象集合等不同形式的数据,例如:

<select id="getUserById" resultMap="UserResultMap">
    select * from users where id = #{id}
</select>

  • <insert>:用于定义插入语句,通常会配置 keyProperty 和 useGeneratedKeys 属性来获取自增主键的值(如果数据库支持自增主键),例如:

<insert id="addUser" keyProperty="id" useGeneratedKeys="true">
    insert into users (username, password) values (#{username}, #{password})
</insert>

  • <update>:定义更新语句,比如更新用户信息等操作,例如:

<update id="updateUser" >
    update users set username = #{username}, password = #{password} where id = #{id}
</update>

  • <delete>:用于定义删除语句,像删除指定用户等情况,例如:

<delete id="deleteUserById">
    delete from users where id = #{id}
</delete>

  • <resultMap>:是 MyBatis 中非常重要的一个标签,用于自定义结果集的映射关系,当数据库表的列名和 Java 对象的属性名不完全一致或者存在复杂的对象关系(一对一、一对多等)时,通过它来精确配置映射规则,例如:

<resultMap id="UserResultMap" type="com.example.entity.User">
    <id property="id" column="user_id"/>
    <result property="username" column="user_name"/>
    <result property="password" column="user_password"/>
    <association property="address" javaType="com.example.entity.Address">
        <id property="id" column="address_id"/>
        <result property="city" column="address_city"/>
        <result property="street" column="address_street"/>
    </association>
</resultMap>

  • <parameterMap>:在早期版本中用于定义参数映射,不过在 MyBatis 3 之后,使用 #{} 或 ${} 占位符结合参数传递的方式基本替代了它的大部分功能,现在已经较少使用了。

  1. 解释一下 MyBatis 中 #{} 和 ${} 的区别。
    • #{}:是预编译处理的占位符,MyBatis 在处理 SQL 语句时,会将 #{} 替换为 ?,然后通过 PreparedStatement 来设置参数值,这样做可以有效防止 SQL 注入攻击,并且能根据参数类型自动进行类型转换等处理,是推荐使用的参数传递方式,例如:

select * from users where username = #{username}

  • ${}:是字符串拼接的方式,MyBatis 会直接将 ${} 中的内容替换到 SQL 语句中,不会进行预编译等安全处理,如果传入的内容包含恶意 SQL 语句片段,就容易引发 SQL 注入问题,不过在某些特定场景下有其用途,比如动态表名、动态排序字段等情况,例如要根据传入的表名动态查询数据:

select * from ${tableName} where id = #{id}

但使用 ${} 时需要特别谨慎,确保传入的内容是安全可靠的,避免安全风险。

四、接口与动态 SQL 相关

  1. MyBatis 中 Mapper 接口和 XML 映射文件是如何关联的?
    Mapper 接口和 XML 映射文件的关联主要通过以下几种方式:

    • 命名空间(namespace):在 XML 映射文件中,需要通过 <mapper namespace="com.example.mapper.UserMapper"> 来指定命名空间,这个命名空间要和对应的 Mapper 接口的全限定类名保持一致,这样 MyBatis 就能根据接口方法名去 XML 文件中查找对应的 SQL 语句定义,例如接口中有 User getUserById(int id) 方法,在 XML 文件中就可以通过 <select id="getUserById"...> 来定义对应的查询 SQL 语句,MyBatis 会将接口方法调用与 XML 中的 SQL 语句对应起来。
    • 方法名与 SQL 语句 id 匹配:在保证命名空间一致的基础上,接口中的方法名要和 XML 映射文件中定义的 SQL 语句的 id 属性值相同(一般是驼峰命名法和下划线命名法之间按照一定规则转换后能对应上,比如 getUserById 方法对应 get_user_by_id 这样的 SQL 语句 id,不过最好保持完全一致更清晰),这样才能正确关联并执行相应的 SQL 语句。
  2. 请举例说明 MyBatis 中的动态 SQL 有哪些用法以及相应的标签?
    MyBatis 提供了丰富的动态 SQL 标签来根据不同条件动态拼接 SQL 语句,常见的有:

    • <if>:用于条件判断,只有当条件满足时,标签内的 SQL 语句片段才会被包含到最终的 SQL 语句中,例如:

<select id="getUsersByCondition" resultMap="UserResultMap">
    select * from users
    <where>
        <if test="username!= null">
            and username = #{username}
        </if>
        <if test="age!= null">
            and age = #{age}
        </if>
    </where>
</select>

这里根据传入的 username 和 age 参数是否为 null 来动态决定是否添加对应的查询条件到 SQL 语句中。

  • <choose><when><otherwise>:相当于 Java 中的 switch 语句,用于多条件选择,只有一个 <when> 分支会被执行,如果所有 <when> 条件都不满足,则执行 <otherwise> 中的语句,例如:

<select id="getDiscountByUserType" resultMap="DiscountResultMap">
    select * from discounts
    <where>
        <choose>
            <when test="userType == 'VIP'">
                and discount_rate = 0.8
            </when>
            <when test="userType == 'NORMAL'">
                and discount_rate = 0.9
            </when>
            <otherwise>
                and discount_rate = 1.0
            </otherwise>
        </choose>
    </where>
</select>

  • <trim>:用于去除 SQL 语句中多余的关键字或空格等,常配合 <if> 等标签使用,比如可以去除 <where> 标签前面多余的 and 或 or 关键字,示例:

<select id="getUsersByCondition" resultMap="UserResultMap">
    select * from users
    <trim prefix="where" prefixOverrides="and|or">
        <if test="username!= null">
            and username = #{username}
        </if>
        <if test="age!= null">
            and age = #{age}
        </if>
    </trim>
</select>

  • <foreach>:用于循环遍历集合或数组,将集合中的元素逐个添加到 SQL 语句中,常用于 in 条件查询等情况,例如:

<select id="getUsersByIds" resultMap="UserResultMap">
    select * from users
    <where>
        <if test="ids!= null and ids.size() > 0">
            id in
            <foreach collection="ids" item="id" open="(" close=")" separator=",">
                #{id}
            </foreach>
        </if>
    </where>
</select>

这里假设传入的 ids 是一个 List<Integer> 类型的集合,通过 <foreach> 标签将集合中的元素拼接成 in 条件中的值列表。

五、缓存相关

  1. MyBatis 有几级缓存,分别是如何工作的?
    MyBatis 有一级缓存和二级缓存:

    • 一级缓存
      • 作用范围:一级缓存是 SqlSession 级别的缓存,也就是在同一个 SqlSession 内,对相同的查询语句进行多次查询时,第一次查询会去数据库获取数据,后续的查询如果没有发生数据修改等影响缓存的情况,就会直接从缓存中获取数据,而不用再次向数据库发起请求,提高了查询效率。
      • 工作原理:当通过 SqlSession 执行查询操作时,MyBatis 会先查看一级缓存中是否已经存在对应的查询结果,如果存在则直接返回缓存中的数据,如果不存在则向数据库发起查询请求,将查询结果存入一级缓存中,供后续相同查询使用。但当执行了插入、更新、删除等会改变数据库数据的操作后,该 SqlSession 的一级缓存会被清空,以保证缓存数据的准确性。
    • 二级缓存
      • 作用范围:二级缓存是 Mapper 级别的缓存,它的作用范围比一级缓存更广,可以跨 SqlSession 使用。也就是说,不同的 SqlSession 对同一个 Mapper 中的相同查询语句进行查询时,如果二级缓存中有相应的数据且数据未过期等,就可以直接从二级缓存中获取数据,进一步提高了查询性能,尤其适用于多线程或者多个请求对相同数据的查询场景。
      • 工作原理:首先要在 MyBatis 的配置文件以及对应的 Mapper 映射文件中开启二级缓存(配置 cacheEnabled 属性等),当一个 SqlSession 执行查询操作并将结果存入二级缓存后,其他 SqlSession 再进行相同查询时,会先查找二级缓存,如果命中缓存则直接返回数据,若未命中则去数据库查询,然后将查询结果存入二级缓存中。二级缓存默认使用 PerpetualCache(一种基于 HashMap 的简单缓存实现),也可以通过配置实现自定义的缓存策略,并且可以设置缓存的过期时间、缓存的大小等参数来更好地管理缓存。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2262911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

web实验二

web实验二 2024.12.19 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>青岛理工大学</title>&l…

纯前端实现更新检测

通过判断打包后的html文件中的js入口是否发生变化&#xff0c;进而实现前端的代码更新 为了使打包后的文件带有hash值&#xff0c;需要对vite打包进行配置 import { defineConfig } from vite; import vue from vitejs/plugin-vue; import { resolve } from path; import AutoI…

云原生周刊:Kubernetes v1.32 正式发布

开源项目推荐 Helmper Helmper 简化了将 Helm Charts导入OCI&#xff08;开放容器倡议&#xff09;注册表的过程&#xff0c;并支持可选的漏洞修复功能。它确保您的 Helm Charts不仅安全存储&#xff0c;还能及时应用最新的安全修复。该工具完全兼容 OCI 标准&#xff0c;能够…

【游戏中orika完成一个Entity的复制及其Entity异步落地的实现】 1.ctrl+shift+a是飞书下的截图 2.落地实现

一、orika工具使用 1)工具类 package com.xinyue.game.utils;import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.DefaultMapperFactory;/*** author 王广帅* since 2022/2/8 22:37*/ public class XyBeanCopyUtil {private static MapperFactory mappe…

如何在繁忙的生活中找到自己的节奏?

目录 一、理解生活节奏的重要性 二、分析当前生活节奏 1. 时间分配 2. 心理状态 3. 身体状况 4. 生活习惯 1. 快慢适中 2. 张弛结合 3. 与目标相符 三、掌握调整生活节奏的策略 1. 设定优先级 2. 合理规划时间 3. 学会拒绝与取舍 4. 保持健康的生活方式 5. 留出…

CORDIC 算法实现 _FPGA

注&#xff1a;本文为 “CORDIC 算法” 相关文章合辑。 未整理去重。 如有内容异常&#xff0c;请看原文。 Cordic 算法的原理介绍 乐富道 2014-01-28 23:05 Cordic 算法知道正弦和余弦值&#xff0c;求反正切&#xff0c;即角度。 采用用不断的旋转求出对应的正弦余弦值&…

鸿蒙学习笔记:用户登录界面

文章目录 1. 提出任务2. 完成任务2.1 创建鸿蒙项目2.2 准备图片资源2.3 编写首页代码2.4 启动应用 3. 实战小结 1. 提出任务 本次任务聚焦于运用 ArkUI 打造用户登录界面。需呈现特定元素&#xff1a;一张图片增添视觉感&#xff0c;两个分别用于账号与密码的文本输入框&#…

着色器 (三)

今天&#xff0c;是我们介绍opengl着色器最后一章&#xff0c;着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之…

leetcode:3285. 找到稳定山的下标(python3解法)

难度&#xff1a;简单 有 n 座山排成一列&#xff0c;每座山都有一个高度。给你一个整数数组 height &#xff0c;其中 height[i] 表示第 i 座山的高度&#xff0c;再给你一个整数 threshold 。 对于下标不为 0 的一座山&#xff0c;如果它左侧相邻的山的高度 严格大于 thresho…

深度学习之超分辨率算法——SRGAN

更新版本 实现了生成对抗网络在超分辨率上的使用 更新了损失函数&#xff0c;增加先验函数 SRresnet实现 import torch import torchvision from torch import nnclass ConvBlock(nn.Module):def __init__(self, kernel_size3, stride1, n_inchannels64):super(ConvBlock…

集成方案 | Docusign + 金蝶云,实现合同签署流程自动化!

本文将详细介绍 Docusign 与金蝶云的集成步骤及其效果&#xff0c;并通过实际应用场景来展示 Docusign 的强大集成能力&#xff0c;以证明 Docusign 集成功能的高效性和实用性。 在当今商业环境中&#xff0c;流程的无缝整合与数据的实时性对于企业的成功至关重要。金蝶云&…

数据结构----链表头插中插尾插

一、链表的基本概念 链表是一种线性数据结构&#xff0c;它由一系列节点组成。每个节点包含两个主要部分&#xff1a; 数据域&#xff1a;用于存储数据元素&#xff0c;可以是任何类型的数据&#xff0c;如整数、字符、结构体等。指针域&#xff1a;用于存储下一个节点&#…

Service Discovery in Microservices 客户端/服务端服务发现

原文链接 Client Side Service Discovery in Microservices - GeeksforGeeks 原文链接 Server Side Service Discovery in Microservices - GeeksforGeeks 目录 服务发现介绍 Server-Side 服务发现 实例&#xff1a; Client-Side 服务发现 实例&#xff1a; 服务发现介绍…

Git连接远程仓库(超详细)

目录 一、Gitee 远程仓库连接 1. HTTPS 方式 2. SSH公钥方式 &#xff08;1&#xff09;账户公钥 &#xff08;2&#xff09;仓库公钥 仓库的 SSH Key 和账户 SSH Key 的区别&#xff1f;​ 二、GitHub远程仓库连接 1. HTTPS方式 2.SSH公钥方式 本文将介绍如何通过 H…

系列4:基于Centos-8.6 Kubernetes多网卡节点Calico选择网卡配置

每日禅语 不动心”是一个人修养和定力的体现&#xff0c;若一个人心无定力&#xff0c;就会被外界环境左右&#xff0c;随外界的境遇而动摇。佛家认为&#xff0c;心是一切的基础&#xff0c;一个人如果想要真正入定&#xff0c;必须先从修心开始。修心即是净心&#xff0c;心灵…

Docker:Dockerfile(补充四)

这里写目录标题 1. Dockerfile常见指令1.1 DockerFile例子 2. 一些其他命令 1. Dockerfile常见指令 简单的dockerFile文件 FROM openjdk:17LABEL authorleifengyangCOPY app.jar /app.jarEXPOSE 8080ENTRYPOINT ["java","-jar","/app.jar"]# 使…

98. 验证二叉搜索树(java)

题目描述&#xff1a; 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 …

微软 Phi-4:小型模型的推理能力大突破

在人工智能领域&#xff0c;语言模型的发展日新月异。微软作为行业的重要参与者&#xff0c;一直致力于推动语言模型技术的进步。近日&#xff0c;微软推出了最新的小型语言模型 Phi-4&#xff0c;这款模型以其卓越的复杂推理能力和在数学领域的出色表现&#xff0c;引起了广泛…

libaom 源码分析:熵编码模块介绍

AV1 熵编码原理介绍 关于AV1 熵编码原理介绍可以参考:AV1 编码标准熵编码技术概述libaom 熵编码相关源码介绍 函数流程图 核心函数介绍 av1_pack_bitstream 函数:该函数负责将编码后的数据打包成符合 AV1 标准的比特流格式;包括写入序列头 OBU 的函数 av1_write_obu_header…

JAVA基于百度AI人脸识别签到考勤系统(开题报告+作品+论文)

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育、辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…