/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.common.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * `MybatisPlusConfig`类是一个Spring的配置类，用于配置MyBatis Plus相关的功能和插件，在整个Spring Boot项目启动时，
 * Spring容器会加载并解析这个配置类，根据其中定义的方法来创建相应的Bean并注入到容器中，从而使MyBatis Plus能够集成到项目中并发挥其强大的功能，
 * 例如数据库操作的便捷性增强、分页功能支持以及乐观锁机制等，确保数据库相关的业务逻辑能够高效、安全地执行。
 *
 * @author lanhai
 */
@Configuration // 表明这个类是一个Spring的配置类，Spring容器会在启动时扫描并解析此类中的配置信息，用于创建和管理相关的Bean。
@MapperScan({"com.yami.shop.**.dao"}) // 用于指定MyBatis的Mapper接口所在的包路径，告诉MyBatis去扫描这些包下的Mapper接口并创建对应的代理实现类，使得可以方便地进行数据库操作，这里采用通配符的方式可以扫描多层级的包下的Mapper接口。
public class MybatisPlusConfig {

    /**
     * 逻辑删除插件相关的配置方法，通过 `@Bean` 注解将返回的对象注册为Spring容器中的一个Bean，供其他地方使用。
     * `@ConditionalOnMissingBean` 注解表示只有在容器中不存在相同类型的Bean时，才会创建并注册这个Bean，避免重复创建。
     * 这里返回 `DefaultSqlInjector` 作为 `ISqlInjector` 类型的Bean，`DefaultSqlInjector` 在MyBatis Plus中是默认的SQL注入器，它实现了一些基础的SQL注入功能，
     * 其中可能就包含了对逻辑删除功能的支持（通过在执行SQL语句时自动添加逻辑删除相关的条件判断等操作），使得在代码中可以方便地使用逻辑删除的特性，而无需手动编写大量的SQL条件判断逻辑。
     *
     * @return 返回 `ISqlInjector` 类型的实例，这里实际返回的是 `DefaultSqlInjector`，用于在MyBatis Plus中实现SQL注入相关功能，特别是逻辑删除相关的功能支持。
     */
    @Bean
    @ConditionalOnMissingBean
    public ISqlInjector sqlInjector() {
        return new DefaultSqlInjector();
    }

    /**
     * mybatis-plus插件配置方法，同样通过 `@Bean` 注解将创建的 `MybatisPlusInterceptor` 对象注册为Spring容器中的Bean，用于配置多个MyBatis Plus的拦截器插件，增强MyBatis Plus的功能。
     * 首先创建了一个 `MybatisPlusInterceptor` 实例，它是MyBatis Plus用于管理多个拦截器插件的核心类，然后通过 `addInnerInterceptor` 方法向其中添加了两个重要的拦截器插件：
     * 1. `PaginationInnerInterceptor(DbType.MYSQL)`：这是用于实现分页功能的拦截器插件，并且指定了数据库类型为 `MYSQL`，意味着它会根据MySQL数据库的特性来生成合适的分页SQL语句，
     *    在进行数据库查询操作时，如果使用了MyBatis Plus提供的分页相关的API，这个拦截器就会自动介入，将原始的查询语句转换为带有分页逻辑的SQL语句，从而实现分页查询功能，方便对大量数据进行分页展示和处理。
     * 2. `OptimisticLockerInnerInterceptor`：这是乐观锁相关的拦截器插件，用于实现乐观锁机制，在多线程并发访问数据库同一条记录进行更新操作时，通过版本号等机制来保证数据的一致性，
     *    避免出现数据冲突和脏数据的情况，它会在更新操作的SQL语句执行过程中自动添加乐观锁相关的条件判断，确保只有在数据版本符合预期的情况下才会执行更新操作，保障了数据的并发安全性。
     * 最后将配置好的 `MybatisPlusInterceptor` 返回，使得这些插件能够在整个项目的MyBatis Plus数据库操作中生效，提升数据库操作的功能性和可靠性。
     *
     * @return 返回配置好的 `MybatisPlusInterceptor` 实例，包含了分页和乐观锁相关的拦截器插件，用于增强MyBatis Plus在数据库操作中的功能，如分页查询和并发控制等。
     */
    @Bean
    public MybatisPlusInterceptor optimisticLockerInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}