您的位置:首页 > 健康 > 美食 > 郑州网络公司联系方式_web开发工程师证书_google学术搜索_培训管理平台

郑州网络公司联系方式_web开发工程师证书_google学术搜索_培训管理平台

2025/4/22 11:56:14 来源:https://blog.csdn.net/m0_74808313/article/details/146998551  浏览:    关键词:郑州网络公司联系方式_web开发工程师证书_google学术搜索_培训管理平台
郑州网络公司联系方式_web开发工程师证书_google学术搜索_培训管理平台

目录

一、MyBatis入门

1. 简介

2. 核心特点

3. MyBatis与JDBC的比较

3.1 基本概念

3.2  主要区别对比

3. 核心组件

4. 工作流程

5. MyBatis 环境配置指南

5.1  添加 Maven 依赖

5.2  创建 MyBatis 核心配置文件

5.3  核心配置文件解读

5.3.1  - 属性配置

5.3.2   - 类型别名

5.3.3   - 环境配置

5.3.4   - 映射器配置

二、基于MyBatis的增删改查操作

1. 入门案例:用户管理系统

1.1 实体类 (User.java)

1.2 Mapper 接口 (UserMapper.java)

1.3 Mapper XML (UserMapper.xml)

1.4 MyBatis 配置文件 (mybatis-config.xml)

1.5 数据库配置文件 (db.properties)

1.6 主程序 (MainApp.java)

1.7 运行结果

2. MyBatis的结果类型

2.1  resultType(简单结果映射)

2.2 resultMap(复杂结果映射)

3. resultMap高级特性

3.1 MyBatis 关联映射详解:association 与 collection

3.1.1  association(一对一关联)

3.1.2 collection(一对多关联)

3.1.3 对比总结

3.2  继承映射(extends)

4. MyBatis 中 #{} 和 ${} 的用法

4.1  #{}(预编译占位符)

4.2  ${}(字符串替换)

4.3  核心区别对比

4.4 SQL 注入

三、MyBatis的动态SQL语句

1.  条件判断

2. , ,  多条件选择

3.  智能 WHERE 子句

4.  智能 SET 子句

5.  自定义修剪

6.  循环遍历

7.  和 

7.1  标签

7.2  标签

四、使用MyBatis动态代理技术实现DAO接口

1. 基本工作原理

2. 动态代理实现原理

3. 与传统 DAO 实现对比

4. MyBatis动态代理实现插入操作案例

项目结构

4.1 数据表

4.2 创建实体类

4.3 创建Mapper接口

4.4 创建Mapper映射文件

4.5 配置MyBatis核心文件

4.6 测试代码

4.7 执行结果

4.8 关键点说明

五、MyBatis与Spring的整合

1.MyBatis与Spring整合案例一(传统整合)

1.1 添加依赖

1.2 实体类及接口

1.3 MyBatis框架相关配置

1.4 Spring框架相关配置

1.4.1 SqlSessionFactoryBean

1.4.2 MapperScannerConfigurer

1.5 主程序

1.6 测试结果

2.MyBatis与Spring整合案例一(全注解)

2.1 配置类

2.2 配置类解析

1. 类级别注解

2. 属性注入

3. 核心配置方法

3.1 PropertySourcesPlaceholderConfigurer

3.2 数据源配置

3.3 SqlSessionFactory 配置


mybatis综合案例https://download.csdn.net/download/m0_74808313/90598995

mybatis-spring全注解案例https://download.csdn.net/download/m0_74808313/90599123

        主要介绍了MyBatis的简介与核心特点、MyBatis与JDBC的比较、MyBatis的工作流程和环境配置;基于MyBatis的增删改查操作、MyBatis的结果类型和参数类型、MyBatis中#和$两种语法进行讲解;MyBatis的动态SQL语句;使用MyBatis动态代理技术实现DAO接口;最后进行MyBatis和Spring的整合。

一、MyBatis入门

1. 简介

        MyBatis 是一款优秀的 持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作,通过简单的 XML 或注解配置,将 Java 对象(POJO)与数据库记录灵活映射。

2. 核心特点

  • 轻量级:无需依赖其他复杂框架,核心库小巧。

  • SQL 与代码分离:SQL 写在 XML 或注解中,与业务逻辑解耦。

  • 灵活的结果映射:支持自动或手动将查询结果映射到 Java 对象(如 POJO、Map 等)。

  • 动态 SQL:提供动态标签(如 ifforeachwhere),灵活构建复杂查询。

  • 缓存机制:支持一级缓存(默认)和二级缓存,提升性能。

3. MyBatis与JDBC的比较

3.1 基本概念

  • JDBC (Java Database Connectivity)

    • Java 提供的标准 API,用于连接和操作关系型数据库。

    • 需要手动编写所有数据库操作代码(连接、SQL、参数设置、结果处理等)。

    • 属于底层数据库访问技术,灵活性高但代码冗余。

  • MyBatis

    • 基于 JDBC 的 持久层框架,封装了 JDBC 的繁琐操作。

    • 通过 XML 或注解配置 SQL,自动处理参数映射和结果集转换。

    • 提供高级功能(如动态 SQL、缓存),减少重复代码。


3.2  主要区别对比

对比项JDBCMyBatis
SQL 管理SQL 硬编码在 Java 代码中,难以维护。SQL 与 Java 代码分离(XML/注解),易维护。
参数绑定手动设置 PreparedStatement 参数(setInt()setString())。自动映射参数(#{param})。
结果集处理手动遍历 ResultSet,转换成对象。自动映射结果集到 Java 对象(POJO、Map 等)。
代码量冗余(需写连接、事务、异常处理等)。简洁(框架封装底层细节)。
动态 SQL需手动拼接字符串(易出错)。支持动态 SQL 标签(<if><foreach>)。
缓存无内置缓存,需自行实现。提供一级缓存(Session 级)和二级缓存(全局)。
事务管理手动控制 commit()/rollback()支持自动或声明式事务(如整合 Spring)。
性能优化依赖开发者经验(如手动批处理)。内置批处理、懒加载等优化机制。
学习成本低(基础 API),但高级优化复杂。中等(需学配置和映射规则)。
适用场景小规模项目或需要极致控制 SQL 的场景。中大型项目,需快速开发、维护性强。

3. 核心组件

  • SqlSessionFactory:通过配置文件(如 mybatis-config.xml)构建,用于创建 SqlSession

  • SqlSession:代表与数据库的一次会话,提供增删改查 API。

  • Mapper 接口:通过注解或 XML 定义 SQL 操作,MyBatis 动态生成实现类。

  • 映射文件(XML):配置 SQL 语句和结果映射(如 UserMapper.xml)。

4. 工作流程

  1. 加载配置

    • 读取全局配置文件 mybatis-config.xml(数据源、插件、缓存等)。

    • 加载 Mapper 文件(XML 或注解定义的 SQL)。

  2. 构建 SqlSessionFactory

    • 通过 SqlSessionFactoryBuilder 解析配置,生成单例的 SqlSessionFactory(生命周期贯穿整个应用)。

  3. 创建 SqlSession

    • 每次数据库操作需要一个 SqlSession(线程不安全,需及时关闭)。

    • 默认使用 Executor 执行 SQL。

  4. Mapper 代理

    • MyBatis 动态生成 Mapper 接口的实现类,将方法调用转换为对应的 SQL 执行。

  5. SQL 执行流程

    • 解析 SQL:替换 #{}/${} 为占位符或直接拼接。

    • 参数映射:将 Java 对象属性映射到 SQL 参数。

    • 执行 JDBC:通过 Statement 执行 SQL。

    • 结果映射:将 ResultSet 转换为 Java 对象(根据 resultType/resultMap)。

  6. 事务与关闭

    • 默认需手动调用 sqlSession.commit() 提交事务。

    • 操作完成后关闭 SqlSession 释放资源。

5. MyBatis 环境配置指南

配置_MyBatis中文网https://mybatis.net.cn/configuration.html

MyBatis 的环境配置主要包括核心配置文件和依赖项的设置。

基本环境配置

5.1  添加 Maven 依赖

<!-- MyBatis 核心依赖 -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version> <!-- 使用最新稳定版本 -->
</dependency><!-- 数据库驱动 (以MySQL为例) -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version>
</dependency>

5.2  创建 MyBatis 核心配置文件

在 resources 目录下创建 mybatis-config.xml:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 实体类别名 --><typeAliases><typeAlias type="com.example.model.User" alias="User"/></typeAliases><!-- 环境配置 --><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/mybatis_db?useSSL=false&amp;serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="password"/></dataSource></environment></environments><!-- 映射器文件配置 --><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>

5.3  核心配置文件解读

5.3.1 <properties> - 属性配置
<properties resource="db.properties"><property name="jdbc.username" value="dev_user"/>
</properties>
  • 作用:定义外部属性或直接内联属性

  • 属性

    • resource:指定外部属性文件路径(classpath 相对路径)

    • url:指定外部属性文件URL(文件系统路径或网络路径)

  • 使用方式${propName} 引用属性值

  • 加载顺序

    1. 先读取<property>子标签的属性

    2. 然后读取resource/url指定的属性文件

    3. 后加载的同名属性会覆盖先加载的

5.3.2  <typeAliases> - 类型别名
<typeAliases><typeAlias type="com.example.User" alias="User"/><package name="com.example.model"/>
</typeAliases>
  • 作用:为 Java 类型设置短名称,简化映射文件配置

  • 两种方式

    1. 单个类别名:<typeAlias>

      • type:完整类名

      • alias:别名(不指定时使用简单类名)

    2. 包扫描:<package>

      • name:包名,自动为该包下的类注册别名(使用简单类名)

5.3.3  <environments> - 环境配置
<environments default="development"><environment id="development"><!-- 事务管理 --><transactionManager type="JDBC"/><!-- 数据源 --><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><!-- 其他数据源属性 --></dataSource></environment>
</environments>
  • default:指定默认环境ID

  • 子标签

    • <environment>:定义一个环境

      • id:环境唯一标识符

    • <transactionManager>:事务管理方式

      • type:JDBC(使用JDBC事务)或 MANAGED(容器管理)

    • <dataSource>:数据源配置

      • type:UNPOOLED(无连接池)/POOLED(自带池)/JNDI

5.3.4  <mappers> - 映射器配置
<mappers><!-- 方式1:XML映射文件 --><mapper resource="mapper/UserMapper.xml"/><!-- 方式2:类路径映射器 --><mapper class="com.example.mapper.UserMapper"/><!-- 方式3:包扫描(接口需与XML同名同路径) --><package name="com.example.mapper"/><!-- 方式4:URL绝对路径 --><mapper url="file:///var/mappers/UserMapper.xml"/>
</mappers>

运行 HTML

  • 作用:注册 SQL 映射文件或映射器接口

  • 四种注册方式

    1. resource:classpath 相对路径

    2. class:映射器接口全限定名

    3. package:包名(自动扫描)

    4. url:文件系统或网络绝对路径

二、基于MyBatis的增删改查操作

1. 入门案例:用户管理系统

使用MyBatis完成基础 CRUD 操作的实现。

数据库表结构

CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,`age` int(11) DEFAULT NULL,`email` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO `user` VALUES (1, '张三', 25, 'zhangsan@example.com');
INSERT INTO `user` VALUES (2, '李四', 30, 'lisi@example.com');

项目结构

src/main/
├── java/
│   └── com/
│       └── example/
│           ├── model/
│           │   └── User.java
│           ├── mapper/
│           │   └── UserMapper.java
│           └── MainApp.java
└── resources/├── mybatis-config.xml├── mapper/└── UserMapper.xml

1.1 实体类 (User.java)

package com.example.model;
@Data
public class User {private Integer id;private String name;private Integer age;private String email;}

1.2 Mapper 接口 (UserMapper.java)

package com.example.mapper;import com.example.model.User;
import java.util.List;public interface UserMapper {// 查询所有用户List<User> selectAllUsers();// 根据ID查询用户User selectUserById(Integer id);// 插入用户int insertUser(User user);// 更新用户int updateUser(User user);// 删除用户int deleteUser(Integer id);
}

1.3 Mapper XML (UserMapper.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">
<mapper namespace="com.example.mapper.UserMapper"><resultMap id="userResultMap" type="com.example.model.User"><id property="id" column="id"/><result property="name" column="name"/><result property="age" column="age"/><result property="email" column="email"/></resultMap><select id="selectAllUsers" resultMap="userResultMap">SELECT * FROM user</select><select id="selectUserById" resultMap="userResultMap" parameterType="int">SELECT * FROM user WHERE id = #{id}</select><insert id="insertUser" parameterType="com.example.model.User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(name, age, email) VALUES(#{name}, #{age}, #{email})</insert><update id="updateUser" parameterType="com.example.model.User">UPDATE user SET name=#{name}, age=#{age}, email=#{email} WHERE id=#{id}</update><delete id="deleteUser" parameterType="int">DELETE FROM user WHERE id=#{id}</delete>
</mapper>

1.4 MyBatis 配置文件 (mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="db.properties"/><typeAliases><package name="com.example.model"/></typeAliases><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/UserMapper.xml"/></mappers>
</configuration>

1.5 数据库配置文件 (db.properties)

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

1.6 主程序 (MainApp.java)

package com.example;import com.example.mapper.UserMapper;
import com.example.model.User;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;public class MainApp {public static void main(String[] args) {String resource = "mybatis-config.xml";InputStream inputStream = null;SqlSession sqlSession = null;try {// 1. 加载MyBatis配置文件inputStream = Resources.getResourceAsStream(resource);// 2. 创建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 3. 获取SqlSessionsqlSession = sqlSessionFactory.openSession();// 4. 测试查询所有用户System.out.println("===== 查询所有用户 =====");List<User> users = userMapper.selectList("com.example.mapper.UserMapper.selectAllUsers");users.forEach(System.out::println);// 5. 测试根据ID查询用户System.out.println("\n===== 根据ID查询用户 =====");User user = userMapper.selectOne("com.example.mapper.UserMapper.selectUserById",1);System.out.println(user);// 6. 测试插入用户System.out.println("\n===== 插入新用户 =====");User newUser = new User();newUser.setName("王五");newUser.setAge(28);newUser.setEmail("wangwu@example.com");int insertCount = userMapper.insert("com.example.mapper.UserMapper.insertUser",newUser);System.out.println("插入记录数: " + insertCount + ", 新用户ID: " + newUser.getId());// 8. 测试更新用户System.out.println("\n===== 更新用户 =====");user.setName("张三三");int updateCount = userMapper.update("com.example.mapper.UserMapper.updateUser",user);System.out.println("更新记录数: " + updateCount);// 9. 测试删除用户System.out.println("\n===== 删除用户 =====");int deleteCount = userMapper.delete("com.example.mapper.UserMapper.deleteUser",2);System.out.println("删除记录数: " + deleteCount);// 提交事务sqlSession.commit();} catch (IOException e) {e.printStackTrace();if (sqlSession != null) {sqlSession.rollback();}} finally {if (sqlSession != null) {sqlSession.close();}if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}}
}

1.7 运行结果

===== 查询所有用户 =====
User{id=1, name='张三', age=25, email='zhangsan@example.com'}
User{id=2, name='李四', age=30, email='lisi@example.com'}===== 根据ID查询用户 =====
User{id=1, name='张三', age=25, email='zhangsan@example.com'}===== 插入新用户 =====
插入记录数: 1, 新用户ID: 3===== 更新用户 =====
更新记录数: 1===== 删除用户 =====
删除记录数: 1

2. MyBatis的结果类型

        MyBatis 提供了两种主要的结果映射方式:resultType 和 resultMap,它们在处理查询结果时有不同的应用场景和特点。

2.1  resultType(简单结果映射)

基本概念

resultType 是最简单的结果映射方式,它直接将查询结果的列映射到 Java 简单类型或 POJO 的属性上。

使用场景

  • 查询结果列名与 Java 对象属性名完全一致(或符合驼峰命名规则)

  • 返回简单类型(如 Integer、String 等)

  • 快速开发简单查询

示例代码

<!-- 返回基本类型 -->
<select id="countAllUsers" resultType="int">SELECT COUNT(*) FROM user
</select><!-- 返回POJO对象(自动映射) -->
<select id="selectUserById" resultType="com.example.model.User">SELECT id, name, age, email FROM user WHERE id = #{id}
</select><!-- 返回Map -->
<select id="selectUserAsMap" resultType="map">SELECT * FROM user WHERE id = #{id}
</select>

自动映射规则

  1. 列名与属性名相同:如数据库列 user_name → Java属性 userName

  2. 开启驼峰命名转换(需配置):

<settings><setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

2.2 resultMap(复杂结果映射)

基本概念

resultMap 是 MyBatis 中最强大的结果映射方式,可以自定义复杂的映射关系。

使用场景

  • 数据库列名与 Java 属性名不一致

  • 处理复杂关联查询(一对一、一对多)

  • 需要自定义类型转换

  • 存在继承关系的映射

基本结构

<resultMap id="自定义映射ID" type="目标Java类型"><!-- 主键映射 --><id property="java属性" column="数据库列"/><!-- 普通字段映射 --><result property="java属性" column="数据库列"/><!-- 关联对象 --><association property="属性名" javaType="类型"/><!-- 集合映射 --><collection property="属性名" ofType="集合元素类型"/>
</resultMap>

示例代码

<resultMap id="userResultMap" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><result property="age" column="user_age"/><result property="email" column="user_email"/>
</resultMap><select id="selectUser" resultMap="userResultMap">SELECT user_id, user_name, user_age, user_email FROM t_user WHERE user_id = #{id}
</select>

3. resultMap高级特性

3.1 MyBatis 关联映射详解:association 与 collection

        在 MyBatis 中,association 和 collection 是 resultMap 中用于处理对象关联关系的两个核心元素,分别对应面向对象中的"一对一"和"一对多"关系。

3.1.1  association(一对一关联)

基本概念

association 用于映射单个对象的关联关系,表示"有一个"(has-a)的关系。

使用场景

  • 用户 和 身份证(一个用户对应一个身份证)

  • 订单 和 客户(一个订单对应一个客户)

  • 学生 和 导师(一个学生对应一个导师)

基础语法

<association property="Java属性名" javaType="关联对象类型"column="传递到嵌套查询的列"select="嵌套查询的ID"resultMap="引用已有的resultMap"autoMapping="true/false"><!-- 可以包含id/result等子元素 -->
</association>

示例代码

方式1:嵌套结果映射

  • 嵌套结果映射:单条SQL通过JOIN获取所有数据

<resultMap id="orderResultMap" type="Order"><id property="id" column="order_id"/><result property="orderNo" column="order_no"/><!-- 关联的用户对象 --><association property="user" javaType="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><result property="email" column="user_email"/></association>
</resultMap><select id="selectOrderWithUser" resultMap="orderResultMap">SELECT o.id as order_id, o.order_no,u.id as user_id, u.name as user_name, u.email as user_emailFROM orders oLEFT JOIN user u ON o.user_id = u.idWHERE o.id = #{id}
</select>

方式2:嵌套查询(N+1查询)

  • 嵌套查询:需要执行多条SQL(N+1问题),但可以延迟加载

<resultMap id="orderResultMap" type="Order"><id property="id" column="id"/><result property="orderNo" column="order_no"/><!-- 通过select触发另一个查询 --><association property="user" column="user_id" javaType="User"select="com.example.mapper.UserMapper.selectUserById"/>
</resultMap><select id="selectOrder" resultMap="orderResultMap">SELECT id, order_no, user_id FROM orders WHERE id = #{id}
</select>
3.1.2 collection(一对多关联)

基本概念

collection 用于映射集合类型的关联关系,表示"有多个"(has-many)的关系。

使用场景

  • 部门 和 员工(一个部门有多个员工)

  • 用户 和 订单(一个用户有多个订单)

  • 博客 和 评论(一篇博客有多条评论)

基础语法

<collection property="Java属性名" ofType="集合元素类型"column="传递到嵌套查询的列"select="嵌套查询的ID"resultMap="引用已有的resultMap"autoMapping="true/false"><!-- 可以包含id/result等子元素 -->
</collection>

方式1:嵌套结果映射

<resultMap id="userWithOrdersMap" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><!-- 订单集合 --><collection property="orders" ofType="Order"><id property="id" column="order_id"/><result property="orderNo" column="order_no"/><result property="amount" column="order_amount"/></collection>
</resultMap><select id="selectUserWithOrders" resultMap="userWithOrdersMap">SELECT u.id as user_id, u.name as user_name,o.id as order_id, o.order_no, o.amount as order_amountFROM user uLEFT JOIN orders o ON u.id = o.user_idWHERE u.id = #{id}
</select>

方式2:嵌套查询

<resultMap id="userResultMap" type="User"><id property="id" column="id"/><result property="name" column="name"/><!-- 通过select触发订单查询 --><collection property="orders" column="id" ofType="Order"select="com.example.mapper.OrderMapper.selectOrdersByUserId"/>
</resultMap><select id="selectUser" resultMap="userResultMap">SELECT id, name FROM user WHERE id = #{id}
</select>
3.1.3 对比总结
特性associationcollection
关联关系一对一一对多
Java类型对象属性集合属性(List、Set等)
标签属性javaTypeofType
典型应用订单-用户、学生-导师用户-订单、部门-员工
查询方式嵌套结果/嵌套查询嵌套结果/嵌套查询
延迟加载支持支持

3.2  继承映射(extends)

resultMap 支持继承机制,可以复用已有的映射定义:

<!-- 基础映射 -->
<resultMap id="baseUserMap" type="User"><id property="id" column="id"/><result property="name" column="username"/><result property="email" column="email"/>
</resultMap><!-- 扩展映射(添加角色集合) -->
<resultMap id="userWithRolesMap" extends="baseUserMap" type="User"><collection property="roles" ofType="Role"><id property="roleId" column="role_id"/><result property="roleName" column="role_name"/></collection>
</resultMap>

4. MyBatis 中 #{} 和 ${} 的用法

        MyBatis 提供了两种参数占位符方式:#{} 和 ${},它们在 SQL 预处理和参数处理上有本质区别,正确使用它们对 SQL 安全和性能至关重要。

4.1  #{}(预编译占位符)

核心特性

  • 预编译处理:MyBatis 会将其转换为 JDBC 的 PreparedStatement 参数占位符 ?

  • 安全:自动防止 SQL 注入

  • 类型处理:自动进行 Java 类型到 JDBC 类型的转换

1. MyBatis 解析 SQL 时会将 #{userId} 替换为 ?
2. 执行时通过 PreparedStatement.setXxx() 安全地设置参数
<select id="selectUserById" resultType="User">SELECT * FROM user WHERE id = #{userId}
</select>

4.2  ${}(字符串替换)

核心特性

  • 直接替换:MyBatis 会直接将内容拼接到 SQL 语句中

  • 风险:存在 SQL 注入风险

  • 无类型转换:原样替换字符串

1. MyBatis 直接将 ${tableName} 替换为实际值
<select id="selectByTable" resultType="map">SELECT * FROM ${tableName} WHERE id = #{id}
</select>

4.3  核心区别对比

特性#{}${}
处理方式预编译参数字符串直接替换
安全性安全,防止SQL注入不安全,存在SQL注入风险
性能高(预编译SQL可重用)低(每次需重新解析SQL)
类型处理自动类型转换无类型转换
适用场景参数值传递非参数值部分(表名、列名等)
空值处理自动处理null值直接拼接可能造成SQL语法错误

4.4 SQL 注入

        SQL注入是指攻击者通过在应用程序的输入参数中插入恶意的SQL代码片段,当这些输入被拼接到SQL语句中执行时,改变了原有SQL的语义。

危险用法(使用 ${} 传递参数)

<select id="unsafeLogin" resultType="User">SELECT * FROM user WHERE username = '${username}' AND password = '${password}'
</select>

攻击者输入:(在mysql中 -- 为注释,相当于Java中的 // )

username = "admin' -- "
password = "任意值"

生成SQL:

SELECT * FROM user WHERE username = 'admin' -- ' AND password = '任意值'

这将绕过密码验证!

三、MyBatis的动态SQL语句

        动态 SQL 是 MyBatis 最强大的特性之一,它允许你根据不同条件动态构建 SQL 语句,避免了在 Java 代码中拼接 SQL 字符串的繁琐和安全隐患。

1. <if> 条件判断

作用:根据条件包含 SQL 片段

<select id="findActiveUsers" resultType="User">SELECT * FROM usersWHERE status = 'ACTIVE'<if test="name != null">AND name like #{name}</if><if test="age != null">AND age = #{age}</if>
</select>

2. <choose><when><otherwise> 多条件选择

作用:类似 Java 的 switch-case 结构

<select id="findUsers" resultType="User">SELECT * FROM usersWHERE<choose><when test="id != null">id = #{id}</when><when test="name != null and email != null">name = #{name} AND email = #{email}</when><otherwise>status = 'ACTIVE'</otherwise></choose>
</select>

3. <where> 智能 WHERE 子句

作用:自动处理 WHERE 关键字和开头的 AND/OR

<select id="searchUsers" resultType="User">SELECT * FROM users<where><if test="name != null">AND name like #{name}</if><if test="email != null">AND email = #{email}</if></where>
</select>

4. <set> 智能 SET 子句

作用:动态生成 UPDATE 语句的 SET 部分

<update id="updateUser">UPDATE users<set><if test="name != null">name = #{name},</if><if test="email != null">email = #{email},</if><if test="age != null">age = #{age},</if></set>WHERE id = #{id}
</update>

5. <trim> 自定义修剪

作用:更灵活地处理 SQL 片段的前后缀

<insert id="insertUser">INSERT INTO users<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">id,</if><if test="name != null">name,</if><if test="email != null">email,</if></trim>VALUES<trim prefix="(" suffix=")" suffixOverrides=","><if test="id != null">#{id},</if><if test="name != null">#{name},</if><if test="email != null">#{email},</if></trim>
</insert>

6. <foreach> 循环遍历

作用:处理集合参数,常用于 IN 条件

<select id="selectUsersInIds" resultType="User">SELECT * FROM usersWHERE id IN<foreach item="item" index="index" collection="list"open="(" separator="," close=")">#{item}</foreach>
</select>

collection 类型处理

  • 数组:array

  • List:list 或自定义参数名

  • Map:map 或自定义参数名

7. <sql> 和 <include>

MyBatis 提供了 <sql> 和 <include> 这对标签来实现 SQL 片段的重用

7.1 <sql> 标签

定义可重用的 SQL 代码片段,类似于编程中的"宏"或"函数"。

基本语法

<sql id="片段唯一ID"><!-- SQL片段内容 -->
</sql>

7.2 <include> 标签

引用已定义的 SQL 片段,将片段内容插入到当前位置。

基本语法

<include refid="片段ID" />
<!-- 可带参数 -->
<include refid="片段ID"><property name="参数名" value="参数值"/>
</include>

示例

<select id="selectUsers" resultType="User">SELECT <include refid="userBaseColumns"/>FROM users<include refid="userWhereClause"/>
</select>

四、使用MyBatis动态代理技术实现DAO接口

        MyBatis 的核心特性之一就是通过动态代理技术自动实现 DAO(Mapper)接口,这种方式避免了传统 DAO 实现类的编写,极大地简化了数据访问层的开发。

        MyBatis进行传统的DAO访问时,在使用 DAO 类实现接口后,我们会通过 SqlSession 对象执行增删改查操作(即人们常说的 CRUD、Create 增加、Retrieve 检索、Update 更改、Delete 删除)。在该类以及其他 DAO 实现类中,可能还有大量其他的 CRUD 操作,而这些操作的执行方式都是相同的。这样就给用户的代码开发带来了大量的重复工作,降低了开发效率。

        为提高开发效率,针对这些重复工作,MyBatis 框架为用户提供了一种简便的数据访问方式,即直接通过配置文件,按照一定的规则进行与接口的映射,自动实现对数据库的访问,从而无须进行 DAO 实现类的开发。接口声明完成以后只需要在使用的时候通过 SqlSession 对象的 getMapper 方法,自动获取对应 DAO 接口的代理对象来完成数据访问。在这个过程中,框架通过 MapperMethod 类(整个代理机制的核心类),对 SqlSession 中的操作进行了封装使用,与我们直接用 SqlSession 对象调用相应的 CRUD 的方法是一样的。

1. 基本工作原理

MyBatis 使用 JDK 动态代理为 Mapper 接口生成代理对象,当调用接口方法时:

  1. 代理对象拦截方法调用

  2. 根据"接口全限定名+方法名"作为 key 查找对应的 SQL 语句

  3. 执行 SQL 并将结果转换为方法的返回类型

2. 动态代理实现原理

核心组件

  • MapperProxyFactory:负责创建Mapper接口的代理实例

  • MapperProxy:实现了InvocationHandler接口,是真正的代理处理器

  • MapperMethod:封装了SQL执行逻辑,是代理机制的核心

工作流程

  1. 初始化阶段

    • MyBatis解析所有Mapper接口和对应的映射文件

    • 为每个Mapper接口创建MapperProxyFactory

    • 将接口方法与映射的SQL语句建立关联

  2. 运行时阶段

    // 获取代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 方法调用流程
    userMapper.selectById(1);
    • 通过JDK动态代理生成Mapper接口的代理对象

    • 调用方法时,MapperProxy拦截方法调用

    • 根据方法名和参数构造MapperMethod并执行

3. 与传统 DAO 实现对比

维度传统DAO模式MyBatis动态代理
代码量需要为每个DAO接口编写实现类零实现类
SQL管理SQL分散在各个DAO方法中集中管理在XML/注解中
维护性修改SQL需要修改Java代码只需修改映射文件
性能直接调用,略高代理调用,略低但可忽略
灵活性高度灵活但复杂约定优于配置

4. MyBatis动态代理实现插入操作案例

MyBatis 动态代理生成 DAO 的步骤如下。

1. 编写数据管理的接口 XxxMapper.java。
2. 编写接口对应的配置文件 XxxMapper.xml。

  •  namespace 必须和 DAO 接口的全路径保持一致(即物理路径的文件名称相同)。
  •  statement 的 id 必须和 DAO 接口的方法名保持一致。
  •  statement 的 resultType 类型必须和方法返回值类型保持一致。

3. 通过 sqlSession.getMapper(类的字节码对象)获取代理之后的 Mapper 实现类对象

项目结构

mybatis-demo/
├── pom.xml                     # Maven 项目配置文件
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── hl/
│   │   │           ├── entity/     # 实体类包
│   │   │           │   └── User.java
│   │   │           ├── mapper/     # Mapper 接口包
│   │   │           │   └── UserMapper.java
│   │   │           └── TestMyBatis.java  # 测试类
│   │   └── resources/
│   │       ├── mybatis-config.xml  # MyBatis 核心配置文件
│   │       └── com/
│   │           └── hl/
│   │               ├── mapper/     # Mapper XML 文件目录
|   |                    └── UserMapper.xml
│   └── test/                     # 测试代码目录(可选)
└── target/                       # Maven 编译输出目录(自动生成)

4.1 数据表

CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL,`password` varchar(50) NOT NULL,`email` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

4.2 创建实体类

// User.java
@Data
package com.hl.entity;public class User {private Integer id;private String username;private String password;private String email; }

4.3 创建Mapper接口

// UserMapper.java
package com.hl.mapper;import com.hl.entity.User;public interface UserMapper {/*** 插入用户数据* @param user 用户对象* @return 影响的行数*/int insertUser(User user);
}

4.4 创建Mapper映射文件

<!-- resources/com/hl/mapper/UserMapper.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">
<mapper namespace="com.example.mapper.UserMapper"><!-- 插入用户 --><insert id="insertUser" parameterType="com.example.entity.User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(username, password, email)VALUES(#{username}, #{password}, #{email})</insert>
</mapper>

4.5 配置MyBatis核心文件

<!-- resources/mybatis-config.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><package name="com.example.entity"/></typeAliases><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/test?useSSL=false"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><!-- mapper包扫描 --><mappers><package name="com.hl.mapper"/></mappers>
</configuration>

4.6 测试代码

// TestMyBatis.java
package com.hl;import com.hl.entity.User;
import com.hl.mapper.UserMapper;
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 java.io.InputStream;public class TestMyBatis {public static void main(String[] args) throws Exception {// 1. 加载配置文件InputStream in = Resources.getResourceAsStream("mybatis-config.xml");// 2. 创建SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);// 3. 获取SqlSessiontry (SqlSession session = factory.openSession()) {// 4. 获取Mapper代理对象UserMapper mapper = session.getMapper(UserMapper.class);// 5. 创建用户对象User user = new User();user.setUsername("testUser");user.setPassword("123456");user.setEmail("test@example.com");// 6. 执行插入操作int result = mapper.insertUser(user);System.out.println("插入结果:" + result);System.out.println("生成的主键ID:" + user.getId());// 7. 提交事务session.commit();}}
}

4.7 执行结果

当运行测试代码后,控制台将输出:

插入结果:1
生成的主键ID:1

4.8 关键点说明

  1. namespace匹配:XML中的namespace必须与Mapper接口的全限定名一致

  2. 位置匹配:Mapper映射文件必须和Mapper接口同包同名

  3. id匹配:XML中的insert语句id必须与接口方法名一致

  4. 参数类型:parameterType指定为实体类全限定名

五、MyBatis与Spring的整合

        MyBatis与Spring框架的整合会将MyBatis代码无缝整合到Spring中。他将允许MyBatis参与到Spring的事物管理中,通过Spring中内置的功能组件,更好的完成对数据库的访问操作。

1.MyBatis与Spring整合案例一(传统整合)

        案例说明:使用MyBatis与Spring整合完成对order的CURD操作

1.1 添加依赖

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.3.3</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.22.0</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.22.0</version></dependency><dependency><groupId>com.zjiecode</groupId><artifactId>wxpusher-java-sdk</artifactId><version>2.1.4</version></dependency></dependencies>

1.2 实体类及接口

Order

package org.rainpet.entity;import java.sql.Date;
import java.time.LocalDateTime;public class Order {private int orderId;private LocalDateTime orderTime;private String orderAddress;private Date orderDate;@Overridepublic String toString() {return "Order{" +"orderId=" + orderId +", orderTime=" + orderTime +", orderAddress='" + orderAddress + '\'' +", orderDate=" + orderDate +'}';}public Date getOrderDate() {return orderDate;}public void setOrderDate(Date orderDate) {this.orderDate = orderDate;}public String getOrderAddress() {return orderAddress;}public void setOrderAddress(String orderAddress) {this.orderAddress = orderAddress;}public int getOrderId() {return orderId;}public void setOrderId(int orderId) {this.orderId = orderId;}public LocalDateTime getOrderTime() {return orderTime;}public void setOrderTime(LocalDateTime orderTime) {this.orderTime = orderTime;}}

OrderDap2

package org.rainpet.dao;import org.rainpet.entity.Order;import java.util.List;public interface OrderDao2 {public Integer save(Order order);public Integer update(Order order);public Integer deleteById(int id);public Order findById(int id);public List<Order> findAll();
}

1.3 MyBatis框架相关配置

mybatisConfig.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><typeAliases><typeAlias type="org.rainpet.entity.Order" alias="order"/></typeAliases><mappers><!--         <package name="org.rainpet.dao"/>--></mappers>
</configuration>

OrderDao2.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">
<mapper namespace="org.rainpet.dao.OrderDao2"><resultMap id="orderMap" type="order"><id column="order_id" property="orderId" jdbcType="INTEGER"/> <!-- 主键 --><result column="order_time" property="orderTime" jdbcType="TIMESTAMP"/><result column="order_address" property="orderAddress" jdbcType="VARCHAR"/></resultMap><!--    order是 com.rainpet.entity.Order的别名--><insert id="save" parameterType="order">insert into `t_order` (order_id, order_time,order_address)values (#{orderId}, #{orderTime},#{orderAddress})</insert><update id="update" parameterType="order">update `t_order` set order_time = #{orderTime}<if test="orderAddress!=null and orderAddress !=''">,order_address = #{orderAddress}</if>where order_id = #{orderId}</update><delete id="deleteById" parameterType="java.lang.Integer">delete from `t_order` where order_id = #{id}</delete><select id="findById" resultMap="orderMap" parameterType="java.lang.Integer">select * from `t_order` where 1=1<if test="id != null and id!='' ">and order_id = #{id}</if></select><select id="findAll" resultMap="orderMap">select * from `t_order`limit 0,10</select>
</mapper>

1.4 Spring框架相关配置

mybatis-spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd
"><!-- 开启注解扫描   --><context:component-scan base-package="org.rainpet"/><!-- 开启事物注解模式   --><tx:annotation-driven transaction-manager="transactionManager"/><!-- 引入db.properties文件   --><context:property-placeholder location="db.properties"/><!-- 1. 配置数据源 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="${db.driver}"/><property name="url" value="${db.url}"/><property name="username" value="${db.username}"/><property name="password" value="${db.password}"/></bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean>
<!--    <mybatis-spring:scan base-package="org.rainpet.dao"/>--><import resource="classpath:mybatisConfig.xml"/><!-- 2. 配置SqlSessionFactory --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="configLocation" value="classpath:mybatisConfig.xml"/><property name="dataSource" ref="dataSource"/><property name="mapperLocations" value="classpath:org/rainpet/dao/*.xml"/></bean><!-- 3. 配置Mapper扫描器 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 扫描所有dao接口 --><property name="basePackage" value="org.rainpet.dao"></property><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property></bean>
</beans>
1.4.1 SqlSessionFactoryBean

功能作用

SqlSessionFactoryBean 是 Spring 提供的工厂 Bean,用于在 Spring 容器中创建 MyBatis 的 SqlSessionFactory

主要配置属性

属性名类型说明
dataSourceDataSource必须属性,设置数据源
configLocationResource指定 MyBatis 全局配置文件路径
mapperLocationsResource[]指定 Mapper XML 文件的位置
typeAliasesPackageString设置类型别名的包名
pluginsInterceptor[]配置 MyBatis 插件
configurationConfiguration直接配置 Configuration 对象
1.4.2 MapperScannerConfigurer

功能作用

MapperScannerConfigurer 是 MyBatis-Spring 提供的 Bean 定义扫描器,用于自动发现 Mapper 接口并注册为 Spring Bean。

主要配置属性

属性名类型说明
basePackageString指定扫描的包路径
sqlSessionFactoryBeanNameString指定 SqlSessionFactory 的 Bean 名称
sqlSessionTemplateBeanNameString指定 SqlSessionTemplate 的 Bean 名称
annotationClassClass指定要扫描的注解类型
markerInterfaceClass指定要扫描的父接口

1.5 主程序

package org.rainpet;import org.rainpet.dao.OrderDao2;
import org.rainpet.entity.Order;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.List;/*** Hello world!**/public class MybatisApp
{public static void main( String[] args ){ApplicationContext context=new ClassPathXmlApplicationContext("mybatis-spring.xml");OrderDao2 orderDao2=context.getBean(OrderDao2.class);List<Order> orderList=orderDao2.findAll();System.out.println(orderList);}
}

1.6 测试结果

可以正常访问

2.MyBatis与Spring整合案例二(全注解)

        通过上述的案例一,spring与mybatis的整合仍不是最简的,还是需要进行xml文件的配置。下面案例将使用全注解的方式进行spring与mybatis的整合。

        案例说明:使用MyBatis与Spring全注解方式整合完成对user的CURD操作

2.1 配置类

        使用注解完成对xml文件的代替

package org.rainpet.config;import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;import javax.sql.DataSource;@ComponentScan("org.rainpet")
@Configuration
@EnableAspectJAutoProxy
@PropertySource("classpath:application.properties")
@MapperScan("org.rainpet.mapper")
public class AppConfig {@Value("${spring.datasource.url}")private String datasourceUrl;@Value("${spring.datasource.username}")private String datasourceUsername;@Value("${spring.datasource.password}")private String datasourcePassword;@Value("${spring.datasource.driver-class-name}")private String datasourceDriverClassName;@Beanpublic static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {return new PropertySourcesPlaceholderConfigurer();}@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = null;try {dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(datasourceDriverClassName);dataSource.setUrl(datasourceUrl);dataSource.setUsername(datasourceUsername);dataSource.setPassword(datasourcePassword);}catch (Exception e){e.printStackTrace();}return dataSource;}@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:org/rainpet/mapper/*.xml"));return sessionFactory;}
}

2.2 配置类解析

1. 类级别注解
@ComponentScan("org.rainpet")
@Configuration
@EnableAspectJAutoProxy
@PropertySource("classpath:application.properties")
@MapperScan("org.rainpet.mapper")
  • @Configuration:标识这是一个 Spring 配置类

  • @ComponentScan("org.rainpet"):指定 Spring 扫描组件的基础包路径

  • @EnableAspectJAutoProxy:启用 Spring AOP 自动代理功能

  • @PropertySource("classpath:application.properties"):加载类路径下的 application.properties 文件

  • @MapperScan("org.rainpet.mapper"):指定 MyBatis Mapper 接口的扫描路径(替代了 XML 配置中的 MapperScannerConfigurer)

2. 属性注入
@Value("${spring.datasource.url}")
private String datasourceUrl;
// 其他类似属性...

这些 @Value 注解从 application.properties 文件中注入数据库连接配置:

  • 数据源 URL

  • 数据库用户名

  • 数据库密码

  • JDBC 驱动类名

3. 核心配置方法
3.1 PropertySourcesPlaceholderConfigurer
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {return new PropertySourcesPlaceholderConfigurer();
}
  • 这个 Bean 用于解析 ${...} 占位符

  • 必须声明为 static 以确保在其他 Bean 初始化前就可用

  • 配合 @PropertySource 使用,使 @Value 注入生效

3.2 数据源配置
@Bean
public DataSource dataSource() {DriverManagerDataSource dataSource = null;try {dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(datasourceDriverClassName);dataSource.setUrl(datasourceUrl);dataSource.setUsername(datasourceUsername);dataSource.setPassword(datasourcePassword);} catch (Exception e) {e.printStackTrace();}return dataSource;
}
  • 创建 Spring 的 DriverManagerDataSource 数据源

  • 使用从属性文件注入的值配置连接参数

  • 注意:生产环境建议使用连接池(如 HikariCP)替代 DriverManagerDataSource

3.3 SqlSessionFactory 配置
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:org/rainpet/mapper/*.xml"));return sessionFactory;
}
  • 创建 MyBatis 的 SqlSessionFactoryBean

  • 设置数据源(依赖上面的 dataSource Bean)

  • 配置 Mapper XML 文件的位置模式:

    • classpath*: 表示搜索所有类路径

    • org/rainpet/mapper/*.xml 指定 XML 文件的具体位置

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com