跳到主要内容
Java java
Spring 配置文件与 MyBatis 核心用法 综述由AI生成 Spring Boot 配置文件的基础知识,包括 properties 和 yaml 格式的对比及使用,以及通过@Value 注解注入配置的方法。接着详细讲解了 MyBatis 框架的使用,涵盖注解与 XML 两种配置方式的 CRUD 操作、动态 SQL 标签(如 trim、if、where、set、foreach)的应用、主键返回机制,以及预编译 SQL 与即时 SQL 的区别及 SQL 注入防护原理。文章提供了完整的代码示例和测试用例,帮助开发者掌握 Spring 与 MyBatis 的核心集成技术。
晚风叙旧 发布于 2026/3/23 更新于 2026/6/3 29K 浏览1. 配置文件
1.1 概述
计算机配置文件用于存储系统、应用程序的设置信息,通常以文本或结构化数据格式 (如 JSON、XML、INI 等) 保存。其核心功能包括:
参数定制 :允许用户或管理员调整软件或硬件的运行参数。
环境适配 :根据不同设备或场景加载特定配置 (如开发/生产环境)。
持久化存储 :确保重启后设置仍生效。
Spring Boot 支持多种类型的配置文件,常见的格式包括 properties、yaml 和 yml,主要用于集中管理应用程序的各种配置参数,简化部署和开发过程中的环境切换。YAML 和 YML 本质上是相同的文件格式,只是文件扩展名的不同,两者在功能和使用上没有区别。
1.2 Properties
Properties 配置文件是最早期的配置文件格式,也是创建 Spring Boot 项目默认的配置格式。采用常见的键值对格式 (key=value),支持 # 开头的注释。
# 应用程序名称
spring.application.name=configuration
# 应用程序端口号
server.port=8080
# 数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/database_name?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
1.3 YAML
采用键值对格式 (key: value),冒号后必须有空格。数据序列化格式,通过缩进表示层级关系,支持 # 开头的注释。
spring:
application:
name: configuration
datasource:
url: jdbc:mysql://127.0.0.1:3306/database_name?characterEncoding=utf8&useSSL=false
username: root
password: root
server:
port: 8080
1.4 优缺点对比
Properties
优点 :语法简单直观,采用 key=value 形式,适合初学者快速上手;与 Java 生态兼容性极强。
缺点 :缺乏层次结构,复杂配置时容易冗余;不支持数据类型定义,所有值均为字符串,需手动转换。
YAML
优点 :层次化结构清晰,通过缩进表示层级,适合复杂配置场景;支持数据类型 (如布尔值、数字),减少手动类型转换。
缺点 :格式错误易导致解析失败 (容易忽略冒号后空格);部分旧版工具链兼容性较差,需额外依赖解析库。
注:Spring Boot 同时支持两种格式,混合使用时若 key 重复,Properties 优先级高于 YAML。
1.5 @Value 注解 作用 :是 Spring 框架提供了一个 @Value 注解 (org.springframework.beans.factory.annotation.Value),用于将外部配置文件中的值注入到 Spring 管理的 Bean 中。
示例 :(Properties 和 YAML 的读取方式相同)
package org.example.configuration.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Value("${spring.application.name}")
private String applicationName;
@Value("${server.port}")
private Integer port;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
public void print () {
System.out.println("applicationName=" + applicationName);
System.out.println("port=" + port);
System.out.println("url=" + url);
System.out.println("username=" + username);
System.out.println("password=" + password);
}
}
package org.example.configuration;
import org.example.configuration.config.Config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class ConfigurationApplication {
public static void main (String[] args) {
ApplicationContext context = SpringApplication.run(ConfigurationApplication.class, args);
Config config = context.getBean(Config.class);
config.print();
}
}
applicationName =configuration
port =8080
url =jdbc:mysql://127.0 .0.1 :3306 /database_name?characterEncoding=utf8&useSSL=false
username =root
password =root
2. MyBatis
2.1 概述 MyBatis 是一款优秀的持久层框架,支持自定义 SQL、存储过程、高级映射以及多种配置方式。它消除了几乎所有的 JDBC 代码和参数的手动设置以及结果集的检索。
支持存储过程 :指的是数据库管理系统 (DBMS) 允许用户创建、存储和执行存储过程的能力。存储过程是一组预编译的 SQL 语句,存储在数据库中,可以被应用程序调用执行。
支持高级映射 :指通过配置或注解实现复杂 SQL 查询结果与 Java 对象之间的灵活转换。其核心目标是简化数据库关联操作,提升开发效率。
支持多种配置方式 :MyBatis 支持注解和 XML 两种配置方式。
2.2 前置操作 引入依赖 :Spring Web,Mybatis Framework,MySQL Driver,Lombok。
在 application.properties/yml 中添加数据库连接信息 :
# 应用程序名称
spring.application.name=configuration
# 应用程序端口号
server.port=8080
# 数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/database_name?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
# 自动驼峰转换
mybatis.configuration.map-underscore-to-camel-case=true
spring:
application:
name: configuration
datasource:
url: jdbc:mysql://127.0.0.1:3306/database_name?characterEncoding=utf8&useSSL=false
username: root
password: root
server:
port: 8080
mybatis:
configuration:
map-underscore-to-camel-case: true
SQL 命名规范 :采用下划线分隔单词 (如 order_detail)。
Java 命名规范 :大驼峰/小驼峰。
2.3 注解
2.3.1 配置 import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BlogMapper {
}
@Mapper 注解:允许开发者直接在接口方法上通过注解配置 SQL 语句,无需编写 XML 映射文件。适用于简单 SQL 场景,能显著减少配置量。
CREATE TABLE blog (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR (128 ),
age INT
);
INSERT INTO blog VALUES (null ,'刘备' ,30 ),(null ,'关羽' ,28 ),(null ,'张飞' ,25 );
import lombok.Data;
@Data
public class PersonInfo {
private Integer id;
private String name;
private Integer age;
public PersonInfo (Integer id, String name, Integer age) {
this .id = id;
this .name = name;
this .age = age;
}
public PersonInfo () {
}
}
2.3.2 CRUD import com.example.spring_mybatis.model.PersonInfo;
import org.apache.ibatis.annotations.*;
@Mapper
public interface BlogMapper {
@Select("select * from blog")
List<PersonInfo> getPersonInfoAll () ;
@Insert("insert into blog values (#{id},#{name},#{age})")
Integer addPerson (PersonInfo person) ;
@Update("update blog set name = #{name},age = #{age} where id = #{id}")
Integer updatePerson (PersonInfo personInfo) ;
@Delete("delete from blog where id = #{id}")
Integer deletePerson (Integer id) ;
}
按住 alt+insert,可在 test 目录下生成以上方法的测试方法。
import com.example.spring_mybatis.model.PersonInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
@Slf4j
class BlogMapperTest {
private final BlogMapper blogMapper;
@Autowired
public BlogMapperTest (BlogMapper blogMapper) {
this .blogMapper = blogMapper;
}
@Test
void getPersonInfoAll () {
List<PersonInfo> personInfoAll = blogMapper.getPersonInfoAll();
log.info("查询成功,personInfoAll:{}" , personInfoAll.toString());
}
@Test
void addPerson () {
Integer ret = blogMapper.addPerson(new PersonInfo (null ,"赵云" ,25 ));
log.info("添加成功,影响行数:{}" , ret.toString());
}
@Test
void updatePerson () {
Integer ret = blogMapper.updatePerson(new PersonInfo (1 ,"刘备" ,35 ));
log.info("更新成功,影响行数:{}" , ret.toString());
}
@Test
void deletePerson () {
Integer ret = blogMapper.deletePerson(4 );
log.info("删除成功,影响行数:{}" , ret.toString());
}
}
2.3.3 @Param 作用 :用于在 Mapper 接口方法中为形式参数指定名称。当方法有多个参数时,通过该注解明确 SQL 中引用的参数名,避免依赖参数顺序。
@Mapper
public interface BlogMapper {
@Update("update blog set name = #{name},age = #{age} where id = #{id}")
Integer updatePersonInfo (@Param("id") Integer userId, @Param("name") String userName, @Param("age") Integer userAge) ;
}
@SpringBootTest
@Slf4j
class BlogMapperTest {
private final BlogMapper blogMapper;
@Autowired
public BlogMapperTest (BlogMapper blogMapper) {
this .blogMapper = blogMapper;
}
@Test
void updatePersonInfo () {
Integer ret = blogMapper.updatePersonInfo(1 ,"刘玄德" ,30 );
log.info("更新成功,影响行数:{}" , ret.toString());
}
}
2.4 XML
2.4.1 配置 import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BlogXMLMapper {
}
mybatis:
mapper-locations: classpath:mybatis/**Mapper.xml
在 resources/mybatis 路径下创建以 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 ="com.example.spring_mybatis.mapper_blog.BlogXMLMapper" > </mapper >
2.4.2 示例 import com.example.spring_mybatis.model_blog.PersonInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface BlogXMLMapper {
List<PersonInfo> getPersonInfoAll () ;
}
id :是 MyBatis 映射文件中 SQL 语句的唯一标识符。需与 Mapper 接口中的方法名一致,保证映射正确。
resultType :指定 SQL 查询结果映射的 Java 对象类型,需为全限定类名。
<mapper namespace ="com.example.spring_mybatis.mapper_blog.BlogXMLMapper" >
<select id ="getPersonInfoAll" resultType ="com.example.spring_mybatis.model_blog.PersonInfo" >
select * from blog
</select >
</mapper >
按住 alt+insert,可在 test 目录下生成以上方法的测试方法。
import com.example.spring_mybatis.model_blog.PersonInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
@Slf4j
class BlogXMLMapperTest {
private final BlogXMLMapper blogXMLMapper;
@Autowired
public BlogXMLMapperTest (BlogXMLMapper blogXMLMapper) {
this .blogXMLMapper = blogXMLMapper;
}
@Test
void getPersonInfoAll () {
List<PersonInfo> personInfoAll = blogXMLMapper.getPersonInfoAll();
log.info("查询成功,personInfoAll:{}" , personInfoAll.toString());
}
}
2.5 动态 SQL 动态 SQL :指在程序运行时根据条件或参数动态生成的 SQL 语句。与静态 SQL 相比,动态 SQL 更具灵活性,适用于需要根据不同条件构建查询的场景。例如,在某些 web/app 进行账号注册时会出现非必填选项。MyBatis 的注解和 XML 两种方式都能实现动态 SQL,但 XML 较为方便,所以下文使用 XML 来实现动态 SQL。
2.5.1 trim 标签
prefix :最终结果添加前缀。
suffix :最终结果添加后缀。
prefixOverrides :去除首部指定内容。
suffixOverrides :去除尾部指定内容。
2.5.2 if 标签 作用 :用于条件判断,通常在 where 或 set 语句中使用。当 test 表达式的值为 true 时,包含标签内的 SQL 片段。
<insert id ="addPersonInfo" >
insert into blog
<trim prefix ="(" suffix =")" suffixOverrides ="," >
<if test ="id != null" > id, </if >
<if test ="name != null" > name, </if >
<if test ="age != null" > age, </if >
</trim >
values
<trim prefix ="(" suffix =")" suffixOverrides ="," >
<if test ="id != null" > #{id}, </if >
<if test ="name != null" > #{name}, </if >
<if test ="age != null" > #{age}, </if >
</trim >
</insert >
2.5.3 where 标签 作用 :替代 SQL 中的 where 关键字。当 if 条件成立时才会加入 SQL 片段,并自动去除第一个子句的 and/or。
<select id ="getPersonInfoByNameAndAge" >
select * from blog
<where >
<if test ="name != null" > and name = #{name} </if >
<if test ="age != null" > and age = #{age} </if >
</where >
</select >
2.5.4 set 标签 作用 :用于 update 语句。当 if 条件成立时才会加入 SQL 片段,并自动去除最后一个子句的逗号。
<update id ="updatePersonInfo" >
update blog
<set >
<if test ="name != null" > name = #{name}, </if >
<if test ="age != null" > age = #{age}, </if >
</set >
<where > and id = #{id} </where >
</update >
2.5.5 foreach 标签
collection :集合参数名。
item :当前元素变量名。
open/close :包围符号。
separator :分隔符。
@Test
void getPersonInfoById () {
ArrayList<Integer> ids = new ArrayList <>();
ids.add(1 );
ids.add(2 );
ids.add(3 );
List<PersonInfo> personInfoById = blogXMLMapper.getPersonInfoById(ids);
System.out.println(personInfoById);
}
<select id ="getPersonInfoById" resultType ="com.example.spring_mybatis.model_blog.PersonInfo" >
select * from blog where id in
<foreach collection ="ids" item ="id" open ="(" close =")" separator ="," >
#{id}
</foreach >
</select >
2.5.6 include 标签 作用 :用于引用 SQL 片段,通过 refid 指定要引用的片段 id。需配合 sql 标签使用,实现代码复用。
<sql id ="collection" > id,name,age </sql >
<select id ="getPersonInfoAll" resultType ="com.example.spring_mybatis.model_blog.PersonInfo" >
select <include refid ="collection" > </include > from blog
</select >
2.6 主键返回 主键返回 :指在数据库插入操作后,自动获取刚插入记录的主键值。在 MyBatis 中使用注解和 XML 都能获取到返回的主键。
@Mapper
public interface BlogMapper {
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into blog values (#{id},#{name},#{age})")
Integer addPerson (PersonInfo person) ;
}
@SpringBootTest
@Slf4j
class BlogMapperTest {
private final BlogMapper blogMapper;
@Autowired
public BlogMapperTest (BlogMapper blogMapper) {
this .blogMapper = blogMapper;
}
@Test
void addPerson () {
PersonInfo personInfo = new PersonInfo (null ,"黄忠" ,60 );
Integer ret = blogMapper.addPerson(personInfo);
log.info("添加成功,影响行数:{},返回的主键值:{}" , ret.toString(), personInfo.getId());
}
}
@SpringBootTest
@Slf4j
class BlogXMLMapperTest {
private final BlogXMLMapper blogXMLMapper;
@Autowired
public BlogXMLMapperTest (BlogXMLMapper blogXMLMapper) {
this .blogXMLMapper = blogXMLMapper;
}
@Test
void addPersonInfo () {
PersonInfo personInfo = new PersonInfo ();
personInfo.setAge(40 );
personInfo.setName("曹操" );
Integer ret = blogXMLMapper.addPersonInfo(personInfo);
log.info("添加成功,影响行数:{},返回的主键值:{}" , ret.toString(), personInfo.getId());
}
}
<insert id ="addPersonInfo" useGeneratedKeys ="true" keyProperty ="id" >
insert into blog
<trim prefix ="(" suffix =")" suffixOverrides ="," >
<if test ="id != null" > id, </if >
<if test ="name != null" > name, </if >
<if test ="age != null" > age, </if >
</trim >
values
<trim prefix ="(" suffix =")" suffixOverrides ="," >
<if test ="id != null" > #{id}, </if >
<if test ="name != null" > #{name}, </if >
<if test ="age != null" > #{age}, </if >
</trim >
</insert >
2.7 预编译/即时 SQL 预编译 SQL (Prepared Statements) :SQL 语句在程序运行前被预先编译并存储在数据库中。执行时只需传递参数,无需重新编译 SQL 语句。
安全性高 :通过参数化查询避免 SQL 注入攻击。参数化查询是一种将 SQL 语句与用户输入数据分离的数据库操作方式,查询语句中使用占位符 (如 ?、@param 等) 代替直接拼接用户输入,执行时通过预编译机制将参数动态绑定到占位符位置。
性能优化 :编译一次,多次执行,减少数据库开销。
即时 SQL (Dynamic SQL) :在程序运行时动态生成并立即编译执行,每次执行都可能涉及完整的 SQL 解析和编译过程。
灵活性高 :可根据运行时条件动态拼接 SQL 语句。
潜在风险 :直接拼接用户输入可能导致 SQL 注入。
性能开销 :每次执行需重新编译。
# 占位符会使用预编译机制,将参数值安全地绑定到 SQL 语句中,防止 SQL 注入攻击。MyBatis 会将 # 替换为 ?,然后通过 JDBC 的预编译功能设置参数值。
$ 占位符直接进行字符串替换,将参数值拼接到 SQL 语句中,不会进行预编译或转义处理。
SQL 注入攻击 :当恶意输入 " 'or 1 = '1 " 时。
@Select("select * from blog where name= #{name}")
List<UserInfo> queryByName (String name) ;
预编译 SQL 会根据参数的类型判断是否需要加引号,上述 name 参数是 String 类型,需要加引号,这就是参数化查询的作用 。最终 SQL:
select * from blog where name = " 'or 1='1 ";
# 整个 'or 1=' 1 会作为 name 的值
@Select("select * from blog where name= '${name}'")
List<UserInfo> queryByName (String name) ;
即时 SQL 不会判断参数类型从而是否添加引号,所以需要手动加上单引号。最终 SQL:
select * from blog where name = '' or1= '1' ;
# 因为 1 = 1 是恒等式,所以该表的数据会被全部查询出来,这就是 SQL 注入
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online