JavaWeb 开发 —— 从 JDBC 到 Mybatis 数据库使用

一、JDBC入门

1.1 JDBC的设计

JDBC(Java Database Connectivity)是Java提供的一套标准API,用于与关系型数据库进行交互。它的设计遵循了"面向接口编程"的思想,通过定义一系列接口(如Connection、Statement、ResultSet),让不同数据库厂商提供各自的实现(驱动程序)。

这种设计的精妙之处在于:解耦了应用代码与具体数据库的依赖。你可以在MySQL、Oracle、PostgreSQL之间自由切换,只需要更换驱动和连接字符串,而不需要修改核心业务代码。

1.2 JDBC的组件

组件 职责定位 生命周期 资源管理
DriverManager 驱动管理器,负责加载数据库驱动 应用级别,全局单例 自动管理,无需手动释放
Connection 数据库连接对象,代表与数据库的会话 请求级别,用完即关 必须手动关闭,否则连接泄漏
Statement SQL语句执行器,用于发送SQL到数据库 临时对象,执行完即关 必须手动关闭,释放数据库资源
ResultSet 结果集对象,封装查询返回的数据 临时对象,遍历完即关 必须手动关闭,释放游标资源

1.3 JDBC入门程序

先创建一个Maven项目,在 pom.xml 中引入以下依赖:

xml 复制代码
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.3</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

创建一个test下的测试类来建立JDBC第一个程序:

java 复制代码
package com.yuki.jdbc;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

@SpringBootTest
class JdbcApplicationTests {

    @Test
    void jdbc_test() throws ClassNotFoundException, SQLException {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.获取数据库连接
        String url="jdbc:mysql://localhost:3306/scott_data";
        String username="root";
        String password="Dairenwen1092";
        Connection connection= DriverManager.getConnection(url,username,password);
        //3.获取sql语句执行对象
        Statement statement= connection.createStatement();
        //4.执行sql语句
        int i=statement.executeUpdate("update emp set EMPNO=7904 where ENAME='FORD'");
        System.out.println("SQL语句执行完毕,影响的记录数为:"+i);
        //5.释放资源
        statement.close();
        connection.close();
    }

}

上面的executeUpdate为更改语句,常见的是执行查询语句,并使用try-with-resources这样可以省去释放连接的步骤:

java 复制代码
 @Test
 public void testSelect() {
      String sql = "SELECT id, username, password, name, age FROM user WHERE username = ? AND password = ?";//采用预编译SQL语句

      String url="jdbc:mysql://localhost:3306/scott_data";
      String username="root";
      String password="Dairenwen1092";


      // try-with-resources:自动关闭实现AutoCloseable的资源,无需手动finally关闭
      try (
              Connection connection= DriverManager.getConnection(url,username,password);
              PreparedStatement pstmt = connection.prepareStatement(sql)
      ) {
          // 设置查询参数,防SQL注入
          pstmt.setString(1, "daqiao");
          pstmt.setString(2, "123456");

          // 结果集也放入try-with-resources自动管理
          try (ResultSet rs = pstmt.executeQuery())//结果集对象
          {
              while (rs.next()) {//将光标从当前位置向前移动一行,并判断当前是否为有效行,返回boolean
                  User user = new User(
                          rs.getInt("id"),
                          rs.getString("username"),
                          rs.getString("password"),
                          rs.getString("name"),
                          rs.getInt("age")
                  );
                  System.out.println(user);
              }
          }
          System.out.println("查询执行完成");

      } catch (SQLException e) {
          e.printStackTrace();
          // 可抛出业务自定义异常,统一异常处理
          throw new RuntimeException("数据库查询失败", e);
      }
  }

  @Data
  public static class User {
      private Integer id;
      private String username;
      private String password;
      private String name;
      private Integer age;

      public User(Integer id, String username, String password, String name, Integer age) {
          this.id = id;
          this.username = username;
          this.password = password;
          this.name = name;
          this.age = age;
      }
  }

为什么预编译的SQL语句比一般的静态SQL语句要好呢?原因如下:

  1. 性能更高

    预编译 SQL 会在第一次执行时被数据库编译、优化并缓存,后续执行相同结构的 SQL 时,可直接复用缓存的执行计划,避免了重复的语法解析和编译开销。在批量执行或频繁执行相似查询的场景下(如循环插入、分页查询),性能提升尤为显著。

  2. 防止 SQL 注入

    这是预编译 SQL 最重要的安全特性。它通过占位符(?) 传递参数,参数值会被数据库当作纯数据处理,而非 SQL 语法的一部分。即使用户输入包含恶意 SQL 片段(如 ' OR '1'='1),也不会被执行,从根本上杜绝了 SQL 注入攻击。

二、MyBatis入门

4.1 MyBatis的诞生背景与设计理念

在理解MyBatis之前,需要思考一个问题:为什么有了JDBC还需要MyBatis?

MyBatis解决了JDBC中几个缺点:

  1. 重复代码泛滥:每次数据库操作都要写连接、关闭、异常处理
  2. SQL与Java代码耦合:SQL语句硬编码在Java代码中,难以维护
  3. 结果集映射繁琐:手动从ResultSet中取值并封装到对象
  4. 参数设置麻烦:需要记住参数索引,容易出错
  5. 缺乏缓存机制:每次查询都要访问数据库

4.2 MyBatis核心概念

核心组件 作用说明 配置方式 生命周期
SqlSessionFactory 会话工厂,创建SqlSession 全局配置文件 应用级别,单例
SqlSession 执行SQL的会话对象 通过工厂创建 请求级别,用完即关
Mapper接口 定义数据库操作方法 接口+注解或XML 无状态,可复用
Mapper XML 配置SQL语句和映射规则 XML文件 启动时加载
Configuration 全局配置对象 mybatis-config.xml 应用级别

4.3 MyBatis入门程序

第一步:添加Maven依赖

xml 复制代码
<!-- pom.xml -->
<dependencies>
<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-webmvc</artifactId>
	</dependency>
	<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>4.0.1</version>
	</dependency>

	<dependency>
		<groupId>com.mysql</groupId>
		<artifactId>mysql-connector-j</artifactId>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<optional>true</optional>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-webmvc-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

第二步:修改application.properties配置文件

xml 复制代码
spring.application.name=Mybatis


# 数据源配置 (DataSource)
# 数据库驱动 (MySQL 8.0+ 用这个,5.x 用 com.mysql.jdbc.Driver)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# 数据库连接地址 (请修改为你的数据库名,这里假设叫 db_test)
spring.datasource.url=jdbc:mysql://localhost:3306/scott_data
# 数据库账号
spring.datasource.username=root
# 数据库密码
spring.datasource.password=Dairenwen1092
#配置mybatis的日志输出
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

第三步:创建实体类(POJO)

java 复制代码
package com.yuki.mybatis.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.time.LocalDate;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp  {
    private Integer empno;
    private String ename;
    private String job;
    private Integer mgr;
    private LocalDate hiredate;
    private BigDecimal sal;
    private BigDecimal comm;
    private Integer deptno;
}

第四步:创建Mapper接口

java 复制代码
package com.yuki.mybatis.mapper;


import com.yuki.mybatis.pojo.Emp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper // 运行时自动创建接口的代理实现类,交给Spring IOC容器管理
public interface EmpMapper {

    /**
     * 查询所有员工信息
     */
    @Select("select * from emp")
    public List<Emp> findAll();//mybatis会自动将查询结果封装成Emp对象

}

第五步:创建Mapper XML映射文件

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">

<!-- UserMapper.xml -->
<!-- namespace必须是Mapper接口的全限定名 -->
<mapper namespace="com.example.mapper.UserMapper">
    
    <!-- 
        resultMap:结果映射配置
        作用:定义数据库字段与Java对象属性的映射关系
        优势:
        1. 可以处理复杂的映射关系
        2. 可以复用,避免重复配置
        3. 支持关联查询和嵌套查询
    -->
    <resultMap id="BaseResultMap" type="User">
        <!-- id标签:映射主键字段 -->
        <id column="id" property="id" jdbcType="BIGINT"/>
        
        <!-- result标签:映射普通字段 -->
        <result column="username" property="username" jdbcType="VARCHAR"/>
        <result column="password" property="password" jdbcType="VARCHAR"/>
        <result column="email" property="email" jdbcType="VARCHAR"/>
        <result column="phone" property="phone" jdbcType="VARCHAR"/>
        <result column="status" property="status" jdbcType="INTEGER"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
    </resultMap>
    
    <!-- 
        sql片段:可复用的SQL代码块
        使用<include>标签引用
    -->
    <sql id="Base_Column_List">
        id, username, password, email, phone, status, create_time, update_time
    </sql>
    
    <!-- 
        select标签:查询语句
        id:对应Mapper接口的方法名
        resultMap:使用定义好的resultMap
        parameterType:参数类型(可省略,MyBatis会自动推断)
    -->
    <select id="selectById" resultMap="BaseResultMap">
        SELECT 
            <include refid="Base_Column_List"/>
        FROM users
        WHERE id = #{id}
    </select>
    
    <!-- 
        #{参数名}:预编译参数占位符,会被替换为?
        优点:防止SQL注入,自动类型转换
    -->
    <select id="selectByUsername" resultMap="BaseResultMap">
        SELECT 
            <include refid="Base_Column_List"/>
        FROM users
        WHERE username = #{username}
    </select>
    
    <!-- 
        resultType:直接指定返回类型(简单映射)
        当字段名与属性名一致(或开启驼峰映射)时可以使用
    -->
    <select id="selectAll" resultType="User">
        SELECT 
            <include refid="Base_Column_List"/>
        FROM users
        ORDER BY create_time DESC
    </select>
    
    <select id="selectByStatus" resultMap="BaseResultMap">
        SELECT 
            <include refid="Base_Column_List"/>
        FROM users
        WHERE status = #{status}
        ORDER BY create_time DESC
    </select>
    
    <!-- 
        动态SQL:根据条件动态生成SQL
        where标签:自动处理AND/OR,去除多余的AND/OR
        if标签:条件判断
    -->
    <select id="selectByConditions" resultMap="BaseResultMap">
        SELECT 
            <include refid="Base_Column_List"/>
        FROM users
        <where>
            <if test="username != null and username != ''">
                AND username LIKE CONCAT('%', #{username}, '%')
            </if>
            <if test="status != null">
                AND status = #{status}
            </if>
        </where>
        ORDER BY create_time DESC
    </select>
    
    <!-- 
        insert标签:插入语句
        useGeneratedKeys:使用数据库生成的主键
        keyProperty:将生成的主键值设置到对象的哪个属性
        keyColumn:数据库主键列名
    -->
    <insert id="insert" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
        INSERT INTO users (
            username, 
            password, 
            email, 
            phone, 
            status, 
            create_time, 
            update_time
        ) VALUES (
            #{username}, 
            #{password}, 
            #{email}, 
            #{phone}, 
            #{status}, 
            NOW(), 
            NOW()
        )
    </insert>
    
    <!-- 
        update标签:更新语句
        set标签:自动处理逗号,去除多余的逗号
        动态更新:只更新不为null的字段
    -->
    <update id="update">
        UPDATE users
        <set>
            <if test="username != null">username = #{username},</if>
            <if test="password != null">password = #{password},</if>
            <if test="email != null">email = #{email},</if>
            <if test="phone != null">phone = #{phone},</if>
            <if test="status != null">status = #{status},</if>
            update_time = NOW()
        </set>
        WHERE id = #{id}
    </update>
    
    <!-- delete标签:删除语句 -->
    <delete id="deleteById">
        DELETE FROM users
        WHERE id = #{id}
    </delete>
    
    <!-- 统计查询 -->
    <select id="count" resultType="int">
        SELECT COUNT(*) FROM users
    </select>
    
</mapper>

第六步:测试代码

java 复制代码
package com.yuki.mybatis;

import com.yuki.mybatis.mapper.EmpMapper;
import com.yuki.mybatis.pojo.Emp;
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//会在单元测试运行时,加载springboot环境
class MybatisApplicationTests {

	@Autowired
	private EmpMapper emp;
	@Test
	void testmapper()
	{
		List<Emp> emplist=emp.findAll();
		emplist.forEach(System.out::println);
	}

}

4.4 MyBatis数据库连接池

mybatis底层内置了一个数据库连接池,其工作流程可分为以下几个关键环节:

1. 连接池初始化

应用启动时,连接池会根据配置参数(如 initialSize预先创建一定数量的数据库连接,并将这些连接放入"空闲连接队列"中等待使用。此时连接并未与数据库断开,而是保持"待命"状态。

2. 连接获取

当应用需要执行数据库操作时,会向连接池"申请"连接:

  • 优先复用空闲连接:连接池先检查"空闲连接队列",如果有可用的空闲连接,直接取出并标记为"活跃连接",交给应用使用。
  • 创建新连接 :如果没有空闲连接,且当前活跃连接数未达到"最大活跃连接数"(如 maxActive),则创建一个新的物理连接并标记为活跃。
  • 等待或超时 :如果活跃连接数已达上限,应用会进入等待状态(可配置 maxWait 等待时间),直到有连接被归还或等待超时抛出异常。

3. 连接使用与归还

应用拿到连接后,执行 SQL 操作(查询、更新等)。操作完成后,不会真正关闭物理连接 ,而是调用 connection.close() 将连接"归还"给连接池:

  • 连接从"活跃连接队列"移除,重新放回"空闲连接队列"。
  • 连接会被重置(如清除事务状态、自动提交设置等),确保下一次复用时的状态一致性。

4. 连接池维护

连接池会定期对连接进行检查和管理:

  • 空闲连接清理 :如果空闲连接数超过最大空闲连接数(maxIdle),或空闲时间超过"最大空闲时间"(minEvictableIdleTimeMillis),连接池会关闭这些多余的物理连接,释放资源。
  • 连接有效性检查 :通过"心跳 SQL"(如 SELECT 1)检测空闲连接是否仍然有效,若连接已失效(如数据库重启、网络断开),则丢弃该连接并创建新的连接补充。

第三方连接池

生产环境通常推荐使用性能更优的第三方连接池(如 HikariDruidDBCP2 )。MyBatis 可通过替换 dataSource 实现集成。

连接池 优势 适用场景
Hikari 速度极快、轻量级、稳定 Spring Boot 默认推荐
Druid 功能强大、监控全面、SQL 防火墙 国内常用,适合需要监控的场景
DBCP2 Apache 出品、稳定可靠 传统项目

由于Mybatis默认集成的就是Hikari,所以这里讲解集成alibaba旗下的Druid方法:

步骤 1:引入依赖

xml 复制代码
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-starter</artifactId>
	<version>1.2.19</version>
</dependency>

步骤 2:修改application.properties配置文件

xml 复制代码
spring.application.name=Mybatis

# 数据源配置 (DataSource)
# 数据库驱动 (MySQL 8.0+ 用这个,5.x 用 com.mysql.jdbc.Driver)
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource//新增这一行
# 数据库连接地址 (请修改为你的数据库名,这里假设叫 db_test)
spring.datasource.url=jdbc:mysql://localhost:3306/scott_data
# 数据库账号
spring.datasource.username=root
# 数据库密码
spring.datasource.password=Dairenwen1092
#配置mybatis的日志输出
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

三、Mybatis中增删改查

下面是接口中定义的crud语句,通过Autowired定义接口可以直接调用,简单了解一下即可,后续会通过xml配置文件来进一步学习新的增删改查:

java 复制代码
@Mapper // 运行时自动创建接口的代理实现类,交给Spring IOC容器管理
public interface EmpMapper {

    /**
     * 查询所有员工信息
     */
    //#{}是预编译sql语句,但${}则是直接替换,存在SQL注入问题
    @Delete("delete from emp where empno=#{empno}")
    public Integer deleteByempno(int empno);

    @Insert("insert into emp values(#{empno},#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})")
    public Integer insert(Emp emp);

    @Update("update emp set empno=#{empno},ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno})")
    public Integer update(Emp emp);

    @Select("select * from emp where empno=#{empno} and ename=#{ename}")
    public List<Emp> select(@Param("empno")Integer empno,@Param("ename")String ename);//mybatis会自动将查询结果封装成Emp对象
    //Param相等于起名字,能准确找到sql中的empno和ename,springboot父工程中包含了相关配置,可以省略,但别的骨架中需要加上!
}

四、Mybatis中xml文件配置

一、全局配置文件(mybatis-config.xml)

全局配置文件用于配置 MyBatis 的核心行为,如数据源、事务、缓存等。其结构和核心标签如下:

1. 顶层结构(按顺序)
xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <!-- 以下标签按顺序排列 -->
  <properties/>        <!-- 1. 属性配置 -->
  <settings/>          <!-- 2. 全局设置 -->
  <typeAliases/>       <!-- 3. 类型别名 -->
  <typeHandlers/>      <!-- 4. 类型处理器 -->
  <objectFactory/>     <!-- 5. 对象工厂 -->
  <plugins/>           <!-- 6. 插件 -->
  <environments/>      <!-- 7. 环境配置 -->
  <databaseIdProvider/><!-- 8. 数据库厂商标识 -->
  <mappers/>           <!-- 9. 映射器注册 -->
</configuration>
2. 核心标签详解
(1)<properties>:引入外部属性文件

用于加载外部配置(如 db.properties),可在配置中通过 ${key} 引用。

xml 复制代码
<properties resource="db.properties">
  <property name="username" value="dev_user"/>
</properties>
(2)<settings>:全局行为设置

开启/关闭 MyBatis 的核心功能,如缓存、懒加载、驼峰命名转换等。

xml 复制代码
<settings>
  <setting name="cacheEnabled" value="true"/>          <!-- 开启二级缓存 -->
  <setting name="lazyLoadingEnabled" value="true"/>     <!-- 开启懒加载 -->
  <setting name="mapUnderscoreToCamelCase" value="true"/><!-- 下划线转驼峰 -->
  <setting name="logImpl" value="SLF4J"/>               <!-- 日志实现 -->
</settings>
(3)<typeAliases>:类型别名

为 Java 类型设置短别名,减少全限定类名的冗余。

xml 复制代码
<typeAliases>
  <!-- 单个别名 -->
  <typeAlias type="com.example.User" alias="User"/>
  <!-- 扫描包下所有类,默认别名为类名首字母小写 -->
  <package name="com.example.entity"/>
</typeAliases>
(4)<environments>:环境配置

配置数据源和事务管理器,可配置多环境(如开发、测试)。

xml 复制代码
<environments default="development">
  <environment id="development">
    <!-- 事务管理器:JDBC/MANAGED -->
    <transactionManager type="JDBC"/>
    <!-- 数据源:UNPOOLED/POOLED/JNDI -->
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>
(5)<mappers>:注册映射文件

告诉 MyBatis 去哪里找 SQL 映射文件。

xml 复制代码
<mappers>
  <!-- 方式1:引用类路径下的文件 -->
  <mapper resource="com/example/mapper/UserMapper.xml"/>
  <!-- 方式2:引用接口类(需注解或同包同名XML) -->
  <mapper class="com.example.mapper.UserMapper"/>
  <!-- 方式3:扫描包下所有Mapper接口 -->
  <package name="com.example.mapper"/>
</mappers>

二、SQL 映射文件(Mapper.xml)

映射文件用于定义 SQL 语句、参数映射和结果集映射,是 MyBatis 的核心。

1. 顶层结构
xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
  <!-- SQL语句、结果映射等 -->
</mapper>
  • namespace:必须与对应 Mapper 接口的全限定名一致。
2. 核心标签
(1)SQL 语句标签
标签 用途 示例
<select> 查询 <select id="getUser" resultType="User">
<insert> 插入(可配置主键返回) <insert id="addUser" useGeneratedKeys="true" keyProperty="id">
<update> 更新 <update id="updateUser">
<delete> 删除 <delete id="deleteUser">

示例:

xml 复制代码
<select id="getUserById" resultType="User">
  SELECT * FROM user WHERE id = #{id}
</select>

<insert id="insertUser" parameterType="User">
  INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>
(2)<resultMap>:结果映射

解决数据库列名与 Java 属性名不一致,或复杂对象映射的问题。

xml 复制代码
<resultMap id="UserResultMap" type="User">
  <!-- 主键映射 -->
  <id column="user_id" property="userId"/>
  <!-- 普通列映射 -->
  <result column="user_name" property="userName"/>
  <!-- 关联对象映射(一对一) -->
  <association property="dept" javaType="Dept">
    <id column="dept_id" property="deptId"/>
    <result column="dept_name" property="deptName"/>
  </association>
  <!-- 集合映射(一对多) -->
  <collection property="orders" ofType="Order">
    <id column="order_id" property="orderId"/>
  </collection>
</resultMap>

<!-- 使用resultMap -->
<select id="getUserDetail" resultMap="UserResultMap">
  SELECT * FROM user u LEFT JOIN dept d ON u.dept_id = d.dept_id
</select>
(3)<sql><include>:SQL 片段复用

定义可重用的 SQL 片段,减少重复代码。

xml 复制代码
<!-- 定义片段 -->
<sql id="Base_Column_List">
  id, name, age, create_time
</sql>

<!-- 引用片段 -->
<select id="getAllUsers" resultType="User">
  SELECT <include refid="Base_Column_List"/> FROM user
</select>
(4)动态 SQL 标签

用于根据条件动态拼接 SQL,避免硬编码。

  • <if>:条件判断
  • <choose>/<when>/<otherwise>:多分支选择
  • <where>/<set>:智能处理 SQL 拼接(如去除多余 AND/逗号)
  • <foreach>:遍历集合(用于 IN 查询或批量插入)

示例:

xml 复制代码
<select id="getUsersByCondition" resultType="User">
  SELECT * FROM user
  <where>
    <if test="name != null and name != ''">
      AND name LIKE CONCAT('%', #{name}, '%')
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
  </where>
</select>

<insert id="batchInsertUsers" parameterType="java.util.List">
  INSERT INTO user (name, age) VALUES
  <foreach collection="list" item="user" separator=",">
    (#{user.name}, #{user.age})
  </foreach>
</insert>
相关推荐
爱吃牛肉的大老虎1 小时前
PostgreSQL基础之安装
数据库·postgresql
yttandb1 小时前
数据库的设计
java·数据库
Gauss松鼠会2 小时前
openGauss数据库源码解析系列文章——存储引擎源码解析(一)
数据库·oracle·性能优化·database·opengauss
云澜哥哥2 小时前
MyBatis 实战指南:特殊符号处理与高效批量操作
java·jvm·mybatis
y = xⁿ2 小时前
【黑马店铺二刷day02】将店铺查询信息添加到Redis中的业务操作
数据库·redis·缓存
oradh2 小时前
Oracle 11g tar包方式安装数据库软件
数据库·oracle
顶点多余2 小时前
Mysql——表的约束
数据库·mysql
SuGarSJL2 小时前
FakeSMTP-2.1.1使用
java·maven
娇娇yyyyyy2 小时前
QT编程(7): Qt主窗口和菜单栏
数据库·qt·microsoft