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

Mybatis的应用及部分特性

初识Mybatis

Mybatis的概念

        MyBatis 是一个Java 持久层框架,核心作用是简化数据库操作,把 SQL 和 Java 代码解耦。

ORM框架

        MyBatis是一个ORM 框架

        所谓ORM 框架,就是把数据库里的表、字段、关系,映射成编程语言里的类、属性、对象引用,从而让我们用“面向对象”的方式去操作关系型数据库,而不用写大量繁复的 JDBC/SQL。

        简而言之,半自动化ORM,将SQL与Java对象映射,不自动生成SQL,只负责把“你写的 SQL”和“你写的 Java 对象”精准地对接起来,半自动化 ORM 是“SQL 与 Java 对象之间的翻译官”。

核心组件

SqlSessionFactory

       作用:  MyBatis 的核心工厂,负责创建和管理  SqlSession  实例。

特点

  • 全局单例:在整个应用中只需要一个实例,线程安全。
  • 初始化:加载 MyBatis 配置文件、解析映射文件,初始化数据库连接池等资源。

功能: 通过  openSession()  方法创建  SqlSession  实例,用于执行 SQL 操作。


SqlSession

作用:MyBatis 的一个会话对象,用于执行 SQL 操作。

特点

  • 线程不安全:每次请求或操作数据库时需要创建一个新的实例,用完后必须关闭。
  • 功能:提供  crud等方法,用于执行 SQL 语句。它还管理事务(提交或回滚)。
  • 生命周期:通常与一个请求或一个业务操作绑定,用完即关闭。
Executor

作用:它是 SqlSession的底层执行器,负责执行 SQL 语句。

类型

  • Simple:每次执行 SQL 时都创建新的 Statement,适合简单场景。
  • Reuse:复用 Statement,减少 Statement 的创建和销毁开销。
  • Batch:批量执行 SQL,适合批量插入或更新操作,可以减少数据库交互次数。

功能:负责执行 SQL 语句,管理 Statement 的生命周期,以及维护一级缓存。


MapperProxy

作用:它是 MyBatis 的动态代理机制,用于实现 Mapper 接口。

特点

  • 动态代理:通过 JDK 动态代理技术,为 Mapper 接口生成代理实例。
  • 功能:将 Mapper 接口的方法调用转换为具体的 SQL 执行操作。
  • 解耦:让开发者只需要关注 Mapper 接口的定义,而不需要关心底层的 SQL 执行细节。

配置文件

此处介绍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>
<!--    配置mybatis的环境--><environments default="mysql">
<!--        id和default的值必须保持一致,接下来配置连接mysql的具体信息--><environment id="mysql">
<!--            配置事务类型  JDBC--><transactionManager type="JDBC"></transactionManager>
<!--            配置数据源  它的取值有POOLED 和 UNPOOLED  前者是mysql提供的默认数据源进行数据库的连接
后者是不使用数据源,多次与数据库进行交互--><dataSource type="POOLED">
<!--                配置连接数据库的驱动 url 用户名和密码--><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments>
<!--    在核心配置文件里要导入接口的映射文件--><mappers><mapper resource="com/noy/dao/UserDao.xml"></mapper></mappers>
</configuration>

Mapper XML 文件

若要通过xml来执行SQL操作,那么Mapper XML配置文件必不可少

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace  命名空间  值必须唯一 一般写接口的全限定名即可
-->
<mapper namespace="com.noy.dao.UserDao">
<!--
select标签  就是一个执行查询操作的标签
id必须和接口方法名称一样,才可以保持映射成功
parameterType参数类型的意思,这里不传参可以不写
resultType 是接口的返回值   如果是泛型 ,写泛型的全限定名
--><select id="findAll" resultType="com.noy.pojo.User">SELECT * FROM user</select>
</mapper>

搭建mybatis入门案例的步骤

  1. 导入mybatis相关的依赖
  2. 创建pojo,将pojo和数据表进行关联映射  定义接口
  3. 创建mybatis的核心配置文件sqlMapConfig.xml
  4. 创建接口的映射文件    接口所在的目录  和接口文件所在的目录保持一致
  5. 编写测试代码

SQL映射

        本质上是解耦 SQL 与 Java 代码,通过声明式配置实现数据库操作

基础 CRUD 标签

标签核心属性
<select>idresultType/resultMap
<insert>idparameterType
<update>idparameterType
<delete>idparameterType

id  必须与 Mapper 接口方法同名,MyBatis 就靠这个把接口方法与 SQL 绑定在一起。

参数 & 占位符

#{}表示一个占位符号 通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,
#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。如果 parameterType 传输单个简单类 型值,#{}括号中可以是 value 或其它名称。${}表示拼接 sql 串 通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换,
${}可以接收简单类型值或 pojo 属性值,如果 parameterType传输单个简单类型值,${}括号中只能是value。

总而言之,安全用  #{} ,拼接才用  ${} 

列表演示:

特性#{} (预编译占位符)${} (字符串替换)
SQL 安全防止 SQL 注入 ✅有注入风险 ❗
类型处理自动类型转换 (Java→JDBC)直接字符串替换
使用场景值参数(WHERE 条件值)动态表名/列名
日志输出? 占位符替换后的完整 SQL

返回结果

resultType :简单场景,直接写全限定类名或别名,列名与属性名一致即可自动映射。
例: <select id="getById" resultType="com.noy.User"> 

resultMap :复杂场景,自定义映射规则(列名≠属性名、一对多、枚举转换等)。
例: <resultMap id="userMap" type="User"><result column="user_name" property="name"/></resultMap> 

主键回填(insert 专属)

 useGeneratedKeys="true"  开启 JDBC 自动生成主键回填。

keyProperty="id"  指定把数据库生成的主键值塞进参数对象的哪个属性。

<insert id="save" parameterType="User"useGeneratedKeys="true" keyProperty="id">INSERT INTO user(name) VALUES(#{name})
</insert>

插入完成后, User#getId()  就能直接拿到新主键。

多级映射

        一个人可能有不同的身份,不同的人可能有同一种身份,不同的人也可能会有不同的身份,所以映射也是如此

关系类型数据库表现对象关系示例MyBatis 标签使用场景
一对一主表外键指向关联表主键用户 ↔ 身份证<association>用户详情页显示身份证信息
一对多主表主键出现在关联表的外键字段部门 ↔ 员工<collection>部门页面显示下属员工列表
多对多通过中间表维护两个主表的关系学生 ↔ 课程两个<collection>学生选课系统/课程学生名单

一对一

        SQL

CREATE TABLE user (id INT PRIMARY KEY,name VARCHAR(50)
);CREATE TABLE id_card (id INT PRIMARY KEY,card_number VARCHAR(20),user_id INT UNIQUE,  -- 唯一外键FOREIGN KEY (user_id) REFERENCES user(id)
);

        Java

public class User {private Integer id;private String name;private IdCard idCard; // 一对一关联对象
}public class IdCard {private String cardNumber;
}

        MyBatis 映射

<resultMap id="userMap" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><!-- 一对一映射 --><association property="idCard" javaType="IdCard"><result property="cardNumber" column="card_number"/></association>
</resultMap><select id="getUserWithCard" resultMap="userMap">SELECT u.id AS user_id, u.name AS user_name,c.card_numberFROM user uJOIN id_card c ON u.id = c.user_idWHERE u.id = #{id}
</select>
一对多

        SQL

CREATE TABLE department (id INT PRIMARY KEY,name VARCHAR(50)
);CREATE TABLE employee (id INT PRIMARY KEY,name VARCHAR(50),dept_id INT,  -- 非唯一外键FOREIGN KEY (dept_id) REFERENCES department(id)
);

        Java

public class Department {private Integer id;private String name;private List<Employee> employees; // 一对多关联集合
}public class Employee {private String name;
}

        MyBatis 映射

<resultMap id="deptMap" type="Department"><id property="id" column="dept_id"/><result property="name" column="dept_name"/><!-- 一对多映射 --><collection property="employees" ofType="Employee"><result property="name" column="emp_name"/></collection>
</resultMap><select id="getDeptWithEmployees" resultMap="deptMap">SELECT d.id AS dept_id,d.name AS dept_name,e.name AS emp_nameFROM department dLEFT JOIN employee e ON d.id = e.dept_idWHERE d.id = #{id}
</select>
多对多

        SQL

CREATE TABLE student (id INT PRIMARY KEY,name VARCHAR(50)
);CREATE TABLE course (id INT PRIMARY KEY,name VARCHAR(50)
);-- 中间表
CREATE TABLE student_course (student_id INT,course_id INT,PRIMARY KEY (student_id, course_id),FOREIGN KEY (student_id) REFERENCES student(id),FOREIGN KEY (course_id) REFERENCES course(id)
);

        Java

public class Student {private Integer id;private String name;private List<Course> courses; // 多对多关联
}public class Course {private String name;private List<Student> students; // 反向关联(可选)
}

       MyBatis 映射

<resultMap id="studentMap" type="Student"><id property="id" column="student_id"/><result property="name" column="student_name"/><!-- 多对多映射(通过中间表) --><collection property="courses" ofType="Course"><result property="name" column="course_name"/></collection>
</resultMap><select id="getStudentWithCourses" resultMap="studentMap">SELECT s.id AS student_id,s.name AS student_name,c.name AS course_nameFROM student sJOIN student_course sc ON s.id = sc.student_idJOIN course c ON sc.course_id = c.idWHERE s.id = #{id}
</select>

实际上,一对多/多对多使用<collection>时,大数据量建议开启延迟加载,具体操作见下列映射策略

映射策略

  • 自动映射:配置 autoMappingBehavior (PARTIAL/FULL/NONE)

  • 嵌套查询<association select="queryDeptById"> + column="dept_id"

  • 延迟加载:在全局启用 lazyLoadingEnabled=true

<settings><!-- 开启全局延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 关闭积极加载(3.4.1+ 默认为 false,高于此版本的mybatis可以不写) --><setting name="aggressiveLazyLoading" value="false"/>
</settings>

动态 SQL用法

其目的为

  • 动态生成 SQL:根据参数条件自动拼接不同 SQL 片段

  • 替代硬编码:避免在 Java 中手动拼接 SQL 字符串

  • 智能去除多余关键字(AND/OR/)

  • 用声明式 XML 标签代替过程式代码拼接,使 SQL 更清晰、更安全、更易维护。

核心标签为

标签作用常用场景
<if>条件判断按需添加 WHERE 条件
<choose>多选一(类似 switch-case)多种查询方案选择
<where>智能处理 WHERE 子句自动去除开头多余的 AND/OR
<set>智能处理 UPDATE 的 SET 子句自动去除尾部逗号
<foreach>遍历集合IN 查询、批量插入

它们的用法语法也类似于Java

基础条件控制 <if>

<select id="search">SELECT * FROM users<where><!-- 姓名不为空时添加条件 --><if test="name != null">AND name = #{name}</if><!-- 年龄大于0时添加条件 --><if test="age > 0">AND age > #{age}</if></where>
</select>

 多分支选择 <choose>

<select id="getData">SELECT * FROM products<where><choose><!-- 优先按ID查 --><when test="id != null">id = #{id}</when><!-- 其次按名称查 --><when test="name != null">name LIKE #{name}</when><!-- 默认查上架商品 --><otherwise>status = 'ON_SALE'</otherwise></choose></where>
</select>

智能更新 <set>

<update id="updateUser">UPDATE users<set><!-- 动态更新字段 --><if test="name != null">name=#{name},</if><if test="email != null">email=#{email},</if>update_time = NOW() <!-- 固定更新 --></set>WHERE id = #{id}
</update>

集合遍历 <foreach>

<!-- IN 查询 -->
<select id="findByIds">SELECT * FROM usersWHERE id IN<foreach item="id" collection="ids" open="(" separator="," close=")">#{id}</foreach>
</select><!-- 批量插入 -->
<insert id="batchInsert">INSERT INTO users (name, age)VALUES<foreach item="user" collection="list" separator=",">(#{user.name}, #{user.age})</foreach>
</insert>

此外,在动态SQL中,WHERE条件 → 用 <where> 标签,UPDATE 操作 → 用 <set> 标签

空集合处理

<!-- 检查集合非空 -->
<if test="list != null and !list.isEmpty()">...
</if>

http://www.dtcms.com/a/316861.html

相关文章:

  • 机器学习——集成学习(Ensemble Learning):随机森林(Random Forest),AdaBoost、Gradient Boosting,Stacking
  • 企业级Redis Cluster部署详解及演练
  • 森赛睿科技成为机器视觉产业联盟会员单位
  • 解决cv::dilate处理后的图像边缘像素出现异常值的问题
  • 结构化设计工具与技术详解
  • Spring 的优势
  • 内部排序算法总结(考研向)
  • 从递归到动态规划-解码方法Ⅱ
  • 软件测试面试如何避坑呢?
  • 8.5 各种攻击实验
  • 使用 BAML 模糊解析改进 LangChain 知识图谱提取:成功率从25%提升到99%
  • 无人机陀螺仪模块技术解析
  • SQL的LEFT JOIN优化
  • 【C语言】动态内存管理详解
  • Centos7 、9 、OpenEuler 22、24对比
  • TCP协议与UDP协议
  • 十六、请求响应-响应:三层架构-分层解耦
  • 信息安全的概述
  • RabbitMQ延时队列的两种实现方式
  • C++算法竞赛篇(九)字符数组题型讲解
  • 坚鹏:AI智能体软件是知行学成为AI智能体创新应用引领者的抓手
  • uvm-register-backdoor-access
  • SpringBoot AI心理学训练实战
  • 更改CodeBuddy的默认terminal为Git Bash
  • 随机森林算法详解:从集成学习原理到代码实现
  • Java技术栈/面试题合集(11)-设计模式篇
  • java web 未完成项目,本来想做个超市管理系统,前端技术还没学。前端是个简单的html。后端接口比较完善。
  • MySQL内外连接详解
  • 学习笔记-相似度匹配改进2
  • 机器学习——随机森林