mybatisPlus篇

1,332 阅读13分钟

概述

MyBatis-Plus(简称 MP)是一个基于 MyBatis 的增强工具,旨在简化开发、提高效率。它在 MyBatis 的基础上提供了许多实用的功能,如自动生成代码、强大的 CRUD 操作、分页插件、性能分析插件等。以下是 MyBatis-Plus 的核心知识点:

 1.核心特性

  • 无侵入:只做增强不做改变,引入 MyBatis-Plus 不会影响现有 MyBatis 功能。
  • 强大的 CRUD 操作:内置通用 Mapper 和 Service,只需少量配置即可实现单表大部分 CRUD 操作。
  • 支持 Lambda 表达式:通过 Lambda 表达式编写查询条件,避免字段硬编码。
  • 自动分页:内置分页插件,支持多种数据库的分页查询。
  • SQL 注入器:支持自定义全局 SQL 方法注入。
  • ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行 CRUD 操作。
  • 代码生成器:自动生成 Entity、Mapper、Service、Controller 等代码,减少重复工作。
  • 性能分析插件:支持 SQL 性能分析,输出 SQL 语句及其执行时间。

2. 核心组件

  • BaseMapper:提供通用的 CRUD 方法,开发者只需继承 BaseMapper 即可使用。
  • IService:Service 层接口,提供更丰富的业务层方法。
  • ServiceImpl:Service 层实现类,继承后可直接使用。
  • QueryWrapper:用于构建查询条件,支持链式调用。
  • LambdaQueryWrapper:基于 Lambda 表达式的查询条件构造器,避免字段硬编码。
  • UpdateWrapper:用于构建更新条件。
  • Page:分页对象,用于分页查询。

3. 常用注解

  • @TableName:指定数据库表名。
  • @TableId:指定主键字段,支持主键策略(如自增、UUID 等)。
  • @TableField:指定数据库字段名,支持字段填充策略(如自动填充创建时间、更新时间)。
  • @Version:乐观锁注解,用于实现乐观锁机制。
  • @EnumValue:枚举类注解,用于标识枚举值与数据库字段的映射关系。

4. CRUD 操作

  • 插入insert(T entity)
  • 删除deleteById(Serializable id)deleteByMap(Map<String, Object> columnMap)delete(Wrapper<T> wrapper)
  • 更新updateById(T entity)update(T entity, Wrapper<T> wrapper)
  • 查询selectById(Serializable id)selectOne(Wrapper<T> wrapper)selectList(Wrapper<T> wrapper)
  • 分页查询selectPage(Page<T> page, Wrapper<T> wrapper)

5. 条件构造器

  • QueryWrapper:用于构建查询条件。

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name", "张三").ge("age", 18);
    List<User> userList = userMapper.selectList(queryWrapper);
    
  • LambdaQueryWrapper:基于 Lambda 表达式的条件构造器。

    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.eq(User::getName, "张三").ge(User::getAge, 18);
    List<User> userList = userMapper.selectList(lambdaQueryWrapper);
    

6. 分页插件

  • 配置分页插件:

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    
  • 使用分页:

    Page<User> page = new Page<>(1, 10); // 当前页,每页大小
    IPage<User> userPage = userMapper.selectPage(page, null);
    List<User> userList = userPage.getRecords();
    

7. 代码生成器

  • 通过代码生成器自动生成 Entity、Mapper、Service、Controller 等代码。

    java

    复制

    AutoGenerator generator = new AutoGenerator();
    generator.setGlobalConfig(globalConfig);
    generator.setDataSource(dataSourceConfig);
    generator.setPackageInfo(packageConfig);
    generator.setStrategy(strategyConfig);
    generator.execute();
    

8. 乐观锁

  • 使用 @Version 注解实现乐观锁。

    @Version
    private Integer version;
    
  • 配置乐观锁插件:

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
    

9. SQL 注入器

  • 自定义全局 SQL 方法:

    public class MySqlInjector extends DefaultSqlInjector {
        @Override
        public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
            List<AbstractMethod> methodList = super.getMethodList(mapperClass);
            methodList.add(new MyCustomMethod());
            return methodList;
        }
    }
    

10. 常见问题

  • 主键策略:默认使用雪花算法生成主键,支持自增、UUID 等。
  • 字段映射:数据库字段名与实体类字段名不一致时,使用 @TableField 注解。
  • 逻辑删除:通过 @TableLogic 注解实现逻辑删除。
  • 多数据源:需要额外配置多数据源支持。

11. 性能优化

  • 使用缓存(如 Redis)减少数据库查询。
  • 避免 N+1 查询问题,使用 @TableField(exist = false) 标注非数据库字段。
  • 使用索引优化查询性能。

12. 与其他框架集成

  • Spring Boot:通过 mybatis-plus-boot-starter 快速集成。
  • Spring Cloud:结合分布式服务框架使用。
  • Swagger:自动生成 API 文档。

13.一级/二级缓存

MyBatis 提供了缓存机制来优化数据库查询性能,主要包括一级缓存二级缓存。以下是它们的核心知识点:


1. 一级缓存

  • 定义:一级缓存是 SqlSession 级别 的缓存,默认开启。

  • 作用范围:同一个 SqlSession 中有效。

  • 生命周期

    • 当 SqlSession 执行 flush(如执行 commitclose 或 clearCache)时,缓存会被清空。
    • 当执行 updateinsertdelete 操作时,缓存也会被清空。
  • 特点

    • 同一个 SqlSession 中,多次执行相同的 SQL 查询,只会查询一次数据库,后续直接从缓存中获取结果。
    • 一级缓存是 MyBatis 默认开启的,无需额外配置。
  • 示例

    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
    // 第一次查询,会访问数据库
    User user1 = userMapper.selectById(1);
    
    // 第二次查询,直接从一级缓存中获取
    User user2 = userMapper.selectById(1);
    
    sqlSession.close();
    

2. 二级缓存

  • 定义:二级缓存是 Mapper 级别 的缓存,多个 SqlSession 共享。

  • 作用范围:同一个 Mapper 的多个 SqlSession 之间共享。

  • 生命周期

    • 二级缓存的生命周期与整个应用相同,只有当数据被更新(如 updateinsertdelete)时,缓存才会被清空。
  • 特点

    • 二级缓存需要手动开启。
    • 二级缓存可以跨 SqlSession 共享数据。
    • 二级缓存默认使用 PerpetualCache 作为缓存实现,但可以配置为其他缓存实现(如 Ehcache、Redis 等)。
  • 配置

    1. 在 MyBatis 配置文件中启用二级缓存:

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

      运行 HTML

    2. 在 Mapper XML 文件中配置缓存:

      <mapper namespace="com.example.UserMapper">
          <cache/>
      </mapper>
      

      运行 HTML

    3. 实体类需要实现 Serializable 接口,因为二级缓存可能将数据序列化到磁盘或通过网络传输。

      public class User implements Serializable {
          private static final long serialVersionUID = 1L;
          // 其他字段
      }
      
  • 示例

    SqlSession sqlSession1 = sqlSessionFactory.openSession();
    UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
    User user1 = userMapper1.selectById(1);
    sqlSession1.close(); // 关闭 SqlSession1,此时数据会存入二级缓存
    
    SqlSession sqlSession2 = sqlSessionFactory.openSession();
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
    User user2 = userMapper2.selectById(1); // 从二级缓存中获取数据
    sqlSession2.close();
    

3. 一级缓存 vs 二级缓存

特性一级缓存二级缓存
作用范围SqlSession 级别Mapper 级别
生命周期SqlSession 生命周期内有效应用生命周期内有效
共享性不共享,仅当前 SqlSession 可用多个 SqlSession 共享
默认开启
配置方式无需配置需在 Mapper XML 中配置 <cache/>
适用场景单会话内重复查询跨会话共享数据

4. 缓存注意事项

  • 脏读问题

    • 一级缓存和二级缓存都可能存在脏读问题(即缓存数据与数据库不一致)。
    • 解决方法:在更新操作后手动清空缓存。
  • 缓存失效

    • 当执行 updateinsertdelete 操作时,缓存会自动清空。
  • 缓存策略

    • 可以通过配置 <cache> 标签的属性来设置缓存策略,如:

      <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
      

      运行 HTML

      • eviction:缓存回收策略(如 FIFO、LRU)。
      • flushInterval:缓存刷新间隔(毫秒)。
      • size:缓存大小。
      • readOnly:是否只读。

5. 自定义缓存

  • MyBatis 支持自定义缓存实现,只需实现 org.apache.ibatis.cache.Cache 接口,并在 Mapper XML 中指定:

    <cache type="com.example.MyCustomCache"/>
    

6. 性能优化建议

  • 一级缓存

    • 适合单会话内重复查询的场景。
    • 避免在长时间会话中缓存大量数据,可能导致内存溢出。
  • 二级缓存

    • 适合跨会话共享数据的场景。
    • 注意缓存的数据量,避免占用过多内存。
    • 对于频繁更新的数据,不建议使用二级缓存。

封装springboot-start-mybatis

涉及技术栈

  • SpringBootStarter的核心原理
  • mybatis
  • mybatisPlus
  • myBatisPlus-Join
  • Maven依赖管理
  • mysql
  • Druid

实现功能

  • 添加分页插件
  • 自动填充参数类

环境搭建

1. 新建一个的maven项目

目录结构

image.png 在pom.xml导入相关依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.byd</groupId>
        <artifactId>frame-framework</artifactId>
        <version>${revision}</version>
    </parent>
    <artifactId>frame-spring-boot-starter-mybatis</artifactId>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.byd</groupId>
            <artifactId>module-common</artifactId>
            <version>${revision}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Web 相关 -->
        <dependency>
            <groupId>com.byd</groupId>
            <artifactId>frame-spring-boot-starter-web</artifactId>
            <version>${revision}</version>
            <scope>provided</scope> <!-- 设置为 provided,只有 OncePerRequestFilter 使用到 -->
        </dependency>
        <!-- DB 相关 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- MyBatis plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
        </dependency>
        <!-- MyBatis 联表查询 -->
        <dependency>
            <groupId>com.github.yulichang</groupId>
            <artifactId>mybatis-plus-join-boot-starter</artifactId>
        </dependency>
        <!-- Druid 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-3-starter</artifactId>
        </dependency>
        <!-- H2-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>



    </dependencies>

    <name>frame-spring-boot-starter-mybatis</name>
    <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
</project>

这里主要是新建一个maven项目将关于mybatisPlus相关依赖导入

2.新建一个SpringBoot项目

目录结构

image.png 在pom.xml导入刚刚新建的maven项目

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.byd</groupId>
        <artifactId>frame_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>test-mybatisplus-demo</artifactId>
    <name>test-mybatisplus-demo</name>
    <url>http://maven.apache.org</url>

    <dependencies>
        <!--自定义的mybatis-->
        <dependency>
            <groupId>com.byd</groupId>
            <artifactId>frame-spring-boot-starter-mybatis</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

按照常规SpringBoot整合MabytisPlus的方式先把项目数据查出来

3.测试

image.png

按照以上步骤完成基本环境搭建后 我们来新增一些功能


扩展功能

1.添加分页插件

编写自动装配的配置类

@SuppressWarnings("SpringComponentScan")
@Configuration
@MapperScan(value = "${frame.info.base-package}", annotationClass = Mapper.class, // 动态配置mapper扫描路径
        lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
public class MybatisAutoConfiguration {
    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
        // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
        return interceptor;
    }
}

MybatisPlusInterceptor是MyBatis-Plus中的一个重要类,它用于配置和注册MyBatis-Plus的拦截器。拦截器是MyBatis提供的一种机制,允许你在SQL执行的不同阶段插入自定义的逻辑。

MybatisPlusInterceptor的主要方法

  1. addInnerInterceptor(InnerInterceptor interceptor) :添加一个内部拦截器。内部拦截器可以拦截SQL语句的执行过程,包括SQL语句的生成、参数的设置、结果的映射等。
  2. addInnerInterceptor(int index, InnerInterceptor interceptor) :在指定位置添加一个内部拦截器。
  3. removeInnerInterceptor(InnerInterceptor interceptor) :移除一个内部拦截器。
  4. removeInnerInterceptor(int index) :移除指定位置的内部拦截器。
  5. clearInnerInterceptors() :清除所有的内部拦截器。

测试

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoTest {
    @Autowired
    private AdminUserMapper userMapper;
    @Test
    public void test() {
        Page<AdminUserDO> adminUserDOPage = new Page<>(1, 10);
        Page<AdminUserDO> adminUserDOPage1 = userMapper.selectPage(adminUserDOPage, null);
        System.out.println(adminUserDOPage1);
    }
}
MyBatis-Plus扩展知识
内置拦截器

MyBatis-Plus提供了一些内置的拦截器,你可以直接使用它们,也可以根据自己的需求自定义拦截器。以下是一些常用的内置拦截器:

  • PaginationInnerInterceptor:用于处理分页查询。
  • TenantLineInnerInterceptor:用于处理多租户。
  • OptimisticLockerInnerInterceptor:用于处理乐观锁。
  • PerformanceInnerInterceptor:用于性能分析
  • DataPermissionInterceptor: 数据权限插件
自定义拦截器

InnerInterceptor接口概述

InnerInterceptor是Mybatis-Plus对Mybatis原生Interceptor接口的增强、提供了更细粒度的拦截方法。它提供MybatisPlusInterceptor统一管理所有插件、每个插件通过现实innerInterceptor接口定义拦截逻辑

核心方法

  • willDoQuery()/willDoUpdate():判断是否执行查询或更新操作
  • beforeQuery()/beforeUpdate():在sql执行前修改SQL或参数
  • beforePrepare():在sql准备阶段拦截(如设置事务超时)
  • beforeGetBoundSql(): 在获取BoundSql前拦截(如动态表名)

BoundSql 是 MyBatis 中的一个核心类,它在 SQL 语句与参数绑定后生成,主要用于表示最终执行的 SQL 语句及其对应的参数映射。当你通过 MyBatis 执行一个查询或更新操作时,MyBatis 首先会解析你定义的 SQL 模板和参数,然后将这些参数绑定到 SQL 语句中形成可直接执行的 SQL 语句,这个结果就是 BoundSql 对象。

内置插件与使用场景

MyBatis-Plus 提供了多个内置的 InnerInterceptor 实现类,覆盖常见需求:

(1) 分页插件(PaginationInnerInterceptor

  • 功能:自动添加 LIMIT 和 OFFSET 分页语句,支持多数据库类型。

  • 配置示例

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    
  • 使用:在 Mapper 方法中传入 Page<T> 对象即可自动分页25。

(2) 防全表操作插件(BlockAttackInnerInterceptor

  • 功能:阻止无 WHERE 条件的全表更新/删除操作。

  • 配置示例

    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
    
  • 效果:若执行 update 或 delete 无 WHERE 条件,抛出异常25。

(3) 数据权限插件(DataPermissionInterceptor

  • 功能:根据用户权限动态添加 SQL 过滤条件(如部门、角色)。

  • 实现步骤

    1. 自定义 DataPermissionHandler 接口,实现 getSqlSegment() 方法。

    2. 将 DataPermissionInterceptor 添加到插件链中:

      DataPermissionInterceptor dataInterceptor = new DataPermissionInterceptor();
      dataInterceptor.setDataPermissionHandler(new CustomDataPermissionHandler());
      interceptor.addInnerInterceptor(dataInterceptor);
      
  • 示例:根据用户部门动态拼接 AND dept_id = ?

(4) 其他插件

  • 乐观锁(OptimisticLockerInnerInterceptor :通过 @Version 注解实现版本控制。
  • 动态表名(DynamicTableNameInnerInterceptor :根据条件动态替换表名52。

 自定义 InnerInterceptor

若内置插件不满足需求,可自定义插件。以下是实现步骤:

(1) 继承 InnerInterceptor 接口

public class CustomInterceptor implements InnerInterceptor {
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        // 修改 SQL 或参数
        String sql = boundSql.getSql();
        sql = sql.replace("old_table", "new_table");
        PluginUtils.mpBoundSql(boundSql).sql(sql);
    }
}

(2) 注册插件

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new CustomInterceptor());
    return interceptor;
}

4. 插件执行顺序与注意事项

  • 执行顺序:插件按添加顺序执行,建议顺序为:

    1. 多租户、动态表名插件
    2. 分页、乐观锁插件
    3. 防全表更新、性能分析插件25。
  • 性能影响:避免在插件中执行耗时操作(如远程调用)。

  • 配置冲突:若同时使用 MyBatis 原生插件和 InnerInterceptor,需注意拦截器链的优先级79。


5. 实际应用案例

案例:SQL 性能监控

通过 PerformanceInterceptor 监控慢查询:

PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(1000); // 设置 SQL 最大执行时间(毫秒)
interceptor.addInnerInterceptor(performanceInterceptor);
  • 日志输出:超时 SQL 会记录警告信息25。

总结

InnerInterceptor 是 MyBatis-Plus 扩展功能的核心接口,通过合理配置内置插件或自定义实现,可以实现分页、数据权限、SQL 优化等高级功能。使用时需注意插件顺序和性能影响,结合业务场景灵活选择插件组合。


2. 配置日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.配置自动填充参数类

 /**
     * 装配 自动填充参数类
     */
    @Bean
    public MetaObjectHandler defaultMetaObjectHandler() {
        return new DefaultDBFieldHandler();
    }
}

/**
 * 通用参数填充实现类
 *
 * 如果没有显式的对通用参数进行赋值,这里会对通用参数进行填充、赋值
 *
 * @author hexiaowu
 */
public class DefaultDBFieldHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
            BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();

            LocalDateTime current = LocalDateTime.now();
            // 创建时间为空,则以当前时间为插入时间
            if (Objects.isNull(baseDO.getCreateTime())) {
                baseDO.setCreateTime(current);
            }
            // 更新时间为空,则以当前时间为更新时间
            if (Objects.isNull(baseDO.getUpdateTime())) {
                baseDO.setUpdateTime(current);
            }
            Long userId = WebFrameworkUtils.getLoginUserId();
            // 当前登录用户不为空,创建人为空,则当前登录用户为创建人
            if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())){
                baseDO.setCreator(userId.toString());
            }
            // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
            if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
                baseDO.setUpdater(userId.toString());
            }
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 更新时间为空,则以当前时间为更新时间
        Object modifyTime = getFieldValByName("updateTime", metaObject);
        if (Objects.isNull(modifyTime)) {
            setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }

        // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
        Object modifier = getFieldValByName("updater", metaObject);
        Long userId = WebFrameworkUtils.getLoginUserId();
        if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
            setFieldValByName("updater", userId.toString(), metaObject);
        }
    }
}

4.主键策略

概述

MyBatis-Plus的主键策略用于自动生成数据库表的主键值、简化开发并确保数据唯一性。以下是主键策略的作用、常见策略及选择建议:

一、常见的主键策略

1.自动递增

  • Mysql:使用AUTO_INCREMENT关键字定义自动增长的整数作为主键
  • PostgreSQL: SERIALBIGSERIAL类型来实现自动递增
  • SQL Server: 使用IDENTITY属性来指定列自动递增
  • Oracle: 没有直接的自动递增特性,但是可以通过序列和触发器实现

使用场景

  • 单实例或主从复制环境下的应用。
  • 需要简单且高效地生成唯一标识符的情况。
  • 对性能要求较高,尤其是写操作频繁的应用

优点

  • 实现简单,易于使用。
  • 能够保证在单个数据库内ID的唯一性。

缺点

  • 不适合分布式系统或多主节点环境,因为可能存在冲突风险。
  • 可能会暴露业务增长信息。

2.UUID

  • 几乎所有现代数据库都支持UUID、通过内置函数如uuid()gen_random_uuid()生成全局唯一的标识符。

适用场景

  • 分布式系统或多数据中心部署。
  • 需要跨多个数据库实例或服务时保持ID全局唯一。
  • 对安全性有要求,不希望轻易推测出下一个ID。

优点

  • 全局唯一性,适用于分布式环境。
  • 增加了数据隐私保护,难以猜测ID序列。

缺点

  • 存储空间较大,索引效率低于整型。
  • 生成和处理速度较慢。

3.序列

  • Oracle:使用CREATE SEQUENCE语句创建序列对象、并通过.NEXTVAL获取下一个值。
  • PostgreSQL:同样支持序列、可以用来为非连续自增的ID提供值
  • 其他数据库: 如Mysql8.0+也引入了对序列的支持

适用场景

  • 类似于自动递增的需求,但在某些数据库中提供了更灵活的配置选项。
  • 当需要非连续自增的ID值时。

优点

  • 提供了比自动递增更多的控制,如缓存大小、起始值等。
  • 在一些情况下可以减少锁竞争,提高并发性能。

缺点

  • 实现上可能比自动递增复杂。
  • 同样存在不适合分布式系统的局限性。