### Complete Spring Boot Configuration Example Source: https://baomidou.com/plugins/optimistic-locker A full Spring Boot configuration example demonstrating how to set up the MybatisPlusInterceptor with OptimisticLockerInnerInterceptor. ```java @Configuration @MapperScan("com.yourpackage.mapper") public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } } ``` -------------------------------- ### Comprehensive Code Generator Setup in Main Method Source: https://baomidou.com/guides/new-code-generator A detailed example of setting up and running the FastAutoGenerator within a main method. It includes author, output directory, Swagger enablement, custom type conversion for SMALLINT, package configuration, table inclusion, prefix filtering, and template engine selection. ```java public static void main(String[] args) { FastAutoGenerator.create("url", "username", "password") .globalConfig(builder -> { builder.author("baomidou") // 设置作者 .enableSwagger() // 开启 swagger 模式 .outputDir("D://"); // 指定输出目录 }) .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> { int typeCode = metaInfo.getJdbcType().TYPE_CODE; if (typeCode == Types.SMALLINT) { // 自定义类型转换 return DbColumnType.INTEGER; } return typeRegistry.getColumnType(metaInfo); }) ) .packageConfig(builder -> builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名 .moduleName("system") // 设置父包模块名 .pathInfo(Collections.singletonMap(OutputFile.xml, "D://")) // 设置mapperXml生成路径 ) .strategyConfig(builder -> builder.addInclude("t_simple") // 设置需要生成的表名 .addTablePrefix("t_", "c_") // 设置过滤表前缀 ) .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板 .execute(); } ``` -------------------------------- ### Chain Query Example Source: https://baomidou.com/guides/data-interface Demonstrates building queries using chain wrappers. The lambda version offers type safety. ```Java // 普通链式查询示例 query().eq("name", "John").list(); // 查询 name 为 "John" 的所有记录 // lambda 链式查询示例 lambdaQuery().eq(User::getAge, 30).one(); // 查询年龄为 30 的单条记录 ``` -------------------------------- ### Example: Save a Single User Source: https://baomidou.com/guides/data-interface Demonstrates how to save a single User entity using the userService.save() method. Shows the generated SQL for the operation. ```java // 假设有一个 User 实体对象 User user = new User(); user.setName("John Doe"); user.setEmail("john.doe@example.com"); boolean result = userService.save(user); // 调用 save 方法 if (result) { System.out.println("User saved successfully."); } else { System.out.println("Failed to save user."); } ``` ```sql INSERT INTO user (name, email) VALUES ('John Doe', 'john.doe@example.com') ``` -------------------------------- ### Generate SQL based on Conditional Logic Source: https://baomidou.com/guides/wrapper These SQL examples show the output of the func method based on the condition within the Consumer. ```sql -- 根据条件生成的 SQL 会有所不同 -- 如果条件为 true,则生成的 SQL 为: SELECT * FROM user WHERE id = 1 -- 如果条件为 false,则生成的 SQL 为: SELECT * FROM user WHERE id != 1 ``` -------------------------------- ### Chain Update Example Source: https://baomidou.com/guides/data-interface Illustrates performing updates using chain wrappers. The lambda version enhances type safety. ```Java // 普通链式更新示例 update().set("status", "inactive").eq("name", "John").update(); // 将 name 为 "John" 的记录 status 更新为 "inactive" // lambda 链式更新示例 User updateUser = new User(); updateUser.setEmail("new.email@example.com"); lambdaUpdate().set(User::getEmail, updateUser.getEmail()).eq(User::getId, 1).update(); // 更新 ID 为 1 的用户的邮箱 ``` -------------------------------- ### Example: Save Multiple Users (Default Batch Size) Source: https://baomidou.com/guides/data-interface Demonstrates how to save a list of User entities using userService.saveBatch() with the default batch size. Shows the generated SQL for the operation. ```java // 假设有一组 User 实体对象 List users = Arrays.asList( new User("Alice", "alice@example.com"), new User("Bob", "bob@example.com"), new User("Charlie", "charlie@example.com") ); // 使用默认批次大小进行批量插入 boolean result = userService.saveBatch(users); // 调用 saveBatch 方法,默认批次大小 if (result) { System.out.println("Users saved successfully."); } else { System.out.println("Failed to save users."); } ``` ```sql INSERT INTO user (name, email) VALUES ('Alice', 'alice@example.com'), ('Bob', 'bob@example.com'), ('Charlie', 'charlie@example.com') ``` -------------------------------- ### mybatis-config.xml Configuration for Plugins Source: https://baomidou.com/plugins Add MyBatis-Plus plugins, including pagination, to your mybatis-config.xml. This example shows how to configure the MybatisPlusInterceptor and PaginationInnerInterceptor. ```xml ``` -------------------------------- ### SimpleQuery Usage Example Source: https://baomidou.com/guides/data-interface Example of using SimpleQuery to extract specific fields (User IDs) from query results and perform side effects like printing and collecting names. ```Java // 假设有一个 User 实体类和对应的 BaseMapper List ids = SimpleQuery.list( Wrappers.lambdaQuery(User.class), // 使用 lambda 查询构建器 User::getId, // 提取的字段,这里是 User 的 id System.out::println, // 第一个 peek 操作,打印每个用户 user -> userNames.add(user.getName()) // 第二个 peek 操作,将每个用户的名字添加到 userNames 列表中 ); ``` -------------------------------- ### Example: Save Multiple Users (Specified Batch Size) Source: https://baomidou.com/guides/data-interface Demonstrates how to save a list of User entities using userService.saveBatch() with a specified batch size. Shows the generated SQL for the operation, split by batch. ```java // 假设有一组 User 实体对象 List users = Arrays.asList( new User("David", "david@example.com"), new User("Eve", "eve@example.com"), new User("Frank", "frank@example.com"), new User("Grace", "grace@example.com") ); // 指定批次大小为 2进行批量插入 boolean result = userService.saveBatch(users, 2); // 调用 saveBatch 方法,指定批次大小 if (result) { System.out.println("Users saved successfully."); } else { System.out.println("Failed to save users."); } ``` ```sql -- 第一批次 INSERT INTO user (name, email) VALUES ('David', 'david@example.com'), ('Eve', 'eve@example.com') -- 第二批次 INSERT INTO user (name, email) VALUES ('Frank', 'frank@example.com'), ('Grace', 'grace@example.com') ``` -------------------------------- ### Basic Code Generator Configuration Source: https://baomidou.com/guides/new-code-generator This snippet shows the basic setup for the FastAutoGenerator using the builder pattern. It configures global settings, package structure, strategy, and template engine. ```java FastAutoGenerator.create("url", "username", "password") .globalConfig(builder -> builder .author("Baomidou") .outputDir(Paths.get(System.getProperty("user.dir")) + "/src/main/java") .commentDate("yyyy-MM-dd") ) .packageConfig(builder -> builder .parent("com.baomidou.mybatisplus") .entity("entity") .mapper("mapper") .service("service") .serviceImpl("service.impl") .xml("mapper.xml") ) .strategyConfig(builder -> builder .entityBuilder() .enableLombok() ) .templateEngine(new FreemarkerTemplateEngine()) .execute(); ``` -------------------------------- ### DDL Schema Initialization for MySQL Source: https://baomidou.com/guides/advanced-features Implement the IDdl interface to define SQL script files for MySQL schema initialization and maintenance. This example specifies two SQL files to be executed. ```java @Component public class MysqlDdl implements IDdl { /** * 执行 SQL 脚本方式 */ @Override public List getSqlFiles() { return Arrays.asList( "db/tag-schema.sql", "D:\\db\\tag-data.sql" ); } } ``` -------------------------------- ### QueryWrapper likeLeft Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper for right fuzzy matching on string fields. Ensures the value is a string. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.likeLeft("name", "王"); ``` -------------------------------- ### H2 Database Configuration in application.yml Source: https://baomidou.com/getting-started Configure H2 database connection details and SQL script locations in application.yml. This setup is for H2; adjust for other databases like MySQL. ```yaml # DataSource Config spring: datasource: driver-class-name: org.h2.Driver username: root password: test sql: init: schema-locations: classpath:db/schema-h2.sql data-locations: classpath:db/data-h2.sql ``` -------------------------------- ### LambdaQueryWrapper likeLeft Example Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper for right fuzzy matching with lambda expressions. Ensures the value is a string. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.likeLeft(User::getName, "王"); ``` -------------------------------- ### QueryWrapper likeRight Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper for left fuzzy matching on string fields. Ensures the value is a string. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.likeRight("name", "王"); ``` -------------------------------- ### Configure Local Cache SQL Parsing Source: https://baomidou.com/plugins Set up a local cache for SQL parsing using JsqlParserGlobal. This example configures Caffeine with a maximum size and expiration time. ```java static { // 默认支持序列化 FstSerialCaffeineJsqlParseCache,JdkSerialCaffeineJsqlParseCache JsqlParserGlobal.setJsqlParseCache(new JdkSerialCaffeineJsqlParseCache( (cache) -> cache.maximumSize(1024) .expireAfterWrite(5, TimeUnit.SECONDS)) ); } ``` -------------------------------- ### QueryWrapper in Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper to set an IN condition for a field, checking if its value is present in a given collection. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.in("age", Arrays.asList(1, 2, 3)); ``` -------------------------------- ### LambdaQueryWrapper likeRight Example Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper for left fuzzy matching with lambda expressions. Ensures the value is a string. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.likeRight(User::getName, "王"); ``` -------------------------------- ### Custom Mapper Methods with Pagination Source: https://baomidou.com/plugins/pagination Examples of defining custom Mapper methods for pagination. The return type can be IPage, a custom page object, or a List. Ensure the IPage parameter is not null when returning IPage. ```java IPage selectPageVo(IPage page, Integer state); ``` ```java // 或者自定义分页类 MyPage selectPageVo(MyPage page); ``` ```java // 或者返回 List List selectPageVo(IPage page, Integer state); ``` -------------------------------- ### Thread-Safe Wrapper Usage Example Source: https://baomidou.com/guides/wrapper Instantiate new Wrapper objects within each method or request to ensure thread safety. This prevents data races in concurrent environments. ```java // 在每个方法或请求中创建新的 Wrapper 实例 public List getUsersByName(String name) { QueryWrapper queryWrapper = Wrappers.query(); queryWrapper.eq("name", name); return userMapper.selectList(queryWrapper); } ``` -------------------------------- ### Code Generator with SQL Query Strategy Source: https://baomidou.com/guides/new-code-generator Example of configuring the code generator to use SQLQuery for data source configuration, including specifying a custom type convert and DB query for MySQL. ```java // MYSQL 示例 切换至SQL查询方式,需要指定好 dbQuery 与 typeConvert 来生成 FastAutoGenerator.create("url", "username", "password") .dataSourceConfig(builder -> builder.databaseQueryClass(SQLQuery.class) .typeConvert(new MySqlTypeConvert()) .dbQuery(new MySqlQuery()) ) // Other Config ... ``` -------------------------------- ### QueryWrapper inSql Example (List) Source: https://baomidou.com/guides/wrapper Use QueryWrapper with inSql to set an IN condition using a comma-separated string of values. Ensure the string is properly formatted. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.inSql("age", "1,2,3,4,5,6"); ``` -------------------------------- ### Custom SQL with Wrapper Example Source: https://baomidou.com/guides/wrapper Define a mapper method to execute custom SQL using `${ew.customSqlSegment}`. Requires MyBatis-Plus version 3.0.7+ and specific parameter naming (`ew` or `@Param(Constants.WRAPPER)`). ```java import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; import org.apache.ibatis.annotations.Param; public interface UserMapper extends BaseMapper { @Select("SELECT * FROM user ${ew.customSqlSegment}") List selectByCustomSql(@Param(Constants.WRAPPER) Wrapper wrapper); } ``` -------------------------------- ### LambdaQueryWrapper inSql Example (List) Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper with a method reference and inSql to set an IN condition using a comma-separated string of values. Ensure the string is properly formatted. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.inSql(User::getAge, "1,2,3,4,5,6"); ``` -------------------------------- ### QueryWrapper inSql Example (Subquery) Source: https://baomidou.com/guides/wrapper Use QueryWrapper with inSql to set an IN condition using a subquery. This allows for dynamic value generation based on another query. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.inSql("id", "select id from other_table where id < 3"); ``` -------------------------------- ### Custom Date Type Handler Implementation Source: https://baomidou.com/reference/annotation Example implementation of a custom `TypeHandler` for `LocalDate` to handle specific date formatting during database operations. ```java import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class CustomDateTypeHandler extends BaseTypeHandler { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @Override public void setNonNullParameter(PreparedStatement ps, int i, LocalDate parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter.format(FORMATTER)); } @Override public LocalDate getNullableResult(ResultSet rs, String columnName) throws SQLException { String dateString = rs.getString(columnName); return (dateString != null) ? LocalDate.parse(dateString, FORMATTER) : null; } // 实现其他必要的方法... } ``` -------------------------------- ### QueryWrapper notLikeLeft Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper to exclude records that start with a specific string. Ensures the value is a string. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.notLikeLeft("name", "王"); ``` -------------------------------- ### Data Scope Annotation for Permissions Source: https://baomidou.com/guides/advanced-features Configure data scope permissions using the @DataScope annotation. This example demonstrates how to specify data columns for filtering based on user roles or departments. ```java @DataScope(type = "test", value = { // 关联表 user 别名 u 指定部门字段权限 @DataColumn(alias = "u", name = "department_id"), // 关联表 user 别名 u 指定手机号字段(自己判断处理) @DataColumn(alias = "u", name = "mobile") }) @Select("select u.* from user u") List selectTestList(IPage page, Long id, @Param("name") String username); ``` -------------------------------- ### LambdaQueryWrapper notLikeLeft Example Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper to exclude records that start with a specific string using lambda expressions. Ensures the value is a string. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.notLikeLeft(User::getName, "王"); ``` -------------------------------- ### QueryWrapper isNull Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper to add an IS NULL condition to a query. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.isNull(User::getName); ``` -------------------------------- ### Improve Startup Speed by Specifying Random Number Generator Source: https://baomidou.com/reference/question Use the `-Djava.security.egd=file:/dev/urandom` JVM argument to change the random number generator source, potentially speeding up startup on Linux systems, especially with HikariCP. ```bash java -Djava.security.egd=file:/dev/urandom -jar xxxx.jar ``` -------------------------------- ### QueryWrapper isNull Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper to check if a field is NULL. Ensure the column name is correct. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.isNull("name"); ``` -------------------------------- ### Generated SQL for allEq Source: https://baomidou.com/guides/wrapper Demonstrates the SQL generated by the allEq method for both regular and Lambda Wrappers, with and without filters. ```sql -- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user WHERE id = 1 AND name = '老王' AND age IS NULL ``` ```sql -- 带过滤器的普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user WHERE name = '老王' AND age IS NULL ``` -------------------------------- ### LambdaQueryWrapper isNull Example Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper to add an IS NULL condition to a query using lambda expressions. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.isNull(User::getName); ``` -------------------------------- ### QueryWrapper notIn Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper to set a NOT IN condition for a field, checking if its value is not present in a given collection. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.notIn("age", Arrays.asList(1, 2, 3)); ``` -------------------------------- ### Add dynamic-datasource-spring-boot-starter Dependency Source: https://baomidou.com/guides/dynamic-datasource Include the starter dependency for Spring Boot 2 to enable dynamic data source functionality. ```xml com.baomidou dynamic-datasource-spring-boot-starter ${version} ``` -------------------------------- ### QueryWrapper notLikeRight Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper to exclude records that end with a specific string. Ensures the value is a string. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.notLikeRight("name", "王"); ``` -------------------------------- ### Add dynamic-datasource-spring-boot3-starter Dependency Source: https://baomidou.com/guides/dynamic-datasource Include the starter dependency for Spring Boot 3 to enable dynamic data source functionality. ```xml com.baomidou dynamic-datasource-spring-boot3-starter ${version} ``` -------------------------------- ### Configure Hosts File for Hostname Resolution Source: https://baomidou.com/reference/question Add your local machine's hostname to the system's hosts file to resolve potential project startup issues related to Snowflake ID initialization. ```text # 示例,例如我的hostname名字为nieqiurong-PC,那我在hosts文件配置如下即可 127.0.0.1 localhost nieqiurong-PC ``` -------------------------------- ### Chain Call vs. Lambda Call Source: https://baomidou.com/guides/wrapper Illustrates the syntax for standard chain calls and lambda-style chain calls, noting that lambda-style is not supported in Kotlin. ```java // 普通链式调用 UpdateChainWrapper update(); // Lambda式链式调用(不支持Kotlin) LambdaUpdateChainWrapper lambdaUpdate(); // 等价示例: query().eq("id", value).one(); lambdaQuery().eq(Entity::getId, value).one(); // 等价示例: update().eq("id", value).remove(); lambdaUpdate().eq(Entity::getId, value).remove(); ``` -------------------------------- ### Execute SQL Script on Secondary MySQL Instance Source: https://baomidou.com/guides/auto-ddl Demonstrates switching to a secondary MySQL instance and executing a SQL script for data manipulation. Note: This specific functionality might be part of enterprise features and not in the open-source version. ```java // 切换到mysql从库,执行SQL脚本 (开源版本无此功能) ShardingKey.change("mysqlt2"); ddlScript.run(new StringReader("DELETE FROM user;\n" + "INSERT INTO user (id, username, password, sex, email) VALUES\n" + "(20, 'Duo', '123456', 0, 'Duo@baomidou.com');")); ``` -------------------------------- ### LambdaQueryWrapper in Example Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper with a method reference to set an IN condition for a field, checking if its value is present in a given collection. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.in(User::getAge, Arrays.asList(1, 2, 3)); ``` -------------------------------- ### notLikeLeft Source: https://baomidou.com/guides/wrapper The `notLikeLeft` method is used to exclude records that start with the specified string. It functions as a negation of right fuzzy matching. ```APIDOC ## notLikeLeft ### Description Used to exclude records that start with the specified string (negation of right fuzzy matching). ### Method Signature ```java notLikeLeft(R column, Object val) notLikeLeft(boolean condition, R column, Object val) ``` ### Parameters * `column` (R): The database field name or a field name using Lambda expression. * `val` (Object): The search value to exclude. * `condition` (boolean): A flag to control whether to apply this condition. ### Request Example **QueryWrapper**: ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.notLikeLeft("name", "王"); ``` **LambdaQueryWrapper**: ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.notLikeLeft(User::getName, "王"); ``` ### Generated SQL ```sql SELECT * FROM user WHERE name NOT LIKE '%王' ``` ### Notes * Ensure the `val` parameter is a string to avoid type conversion errors. * Use `notLike` or `notLikeRight` for full or left fuzzy matching exclusion respectively. ``` -------------------------------- ### Configure Code Generator for Repository Creation Source: https://baomidou.com/reference/question This snippet demonstrates how to configure Baomidou's `AutoGenerator` to produce `Repository` interfaces and implementations instead of the default `Service` interfaces. It involves setting package information and strategy configurations. ```java AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG); generator.packageInfo(new PackageConfig.Builder() .service("repository") .serviceImpl("repository.impl") .build()); generator.strategy( new StrategyConfig.Builder() .serviceBuilder().convertServiceFileName(entityName -> "I" + entityName + "Repository") .superServiceClass(IRepository.class).convertServiceImplFileName(entityName -> entityName + "Repository") .superServiceImplClass(CrudRepository.class) .build()); generator.execute(); ``` -------------------------------- ### Configure Optimistic Locker Plugin (Spring Boot Annotation) Source: https://baomidou.com/plugins/optimistic-locker Configure the MybatisPlusInterceptor with OptimisticLockerInnerInterceptor using Java annotations in Spring Boot. ```java @Configuration @MapperScan("按需修改") public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } } ``` -------------------------------- ### QueryWrapper notInSql Example Source: https://baomidou.com/guides/wrapper Use QueryWrapper with notInSql to set a NOT IN condition using a SQL string. This is useful for complex exclusion criteria. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.notInSql("age", "select id from other_table where id < 3"); ``` -------------------------------- ### SimpleQuery Utility Imports Source: https://baomidou.com/guides/data-interface Imports necessary classes for using the SimpleQuery utility, which facilitates Stream-based processing of query results. ```Java import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; import com.baomidou.mybatisplus.core.toolkit.support.SimpleQuery; ``` -------------------------------- ### LambdaQueryWrapper notIn Example Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper with a method reference to set a NOT IN condition for a field, checking if its value is not present in a given collection. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.notIn(User::getAge, Arrays.asList(1, 2, 3)); ``` -------------------------------- ### Chain Query Wrapper Initialization Source: https://baomidou.com/guides/data-interface Initializes chain query wrappers for building database queries in a fluent style. Supports both standard and lambda expressions. ```Java QueryChainWrapper query(); LambdaQueryChainWrapper lambdaQuery(); ``` -------------------------------- ### Get Lambda Wrapper from UpdateWrapper Source: https://baomidou.com/guides/wrapper Obtain a LambdaUpdateWrapper from an UpdateWrapper to use lambda expressions for type-safe updates. Ensure UpdateWrapper is initialized. ```java UpdateWrapper updateWrapper = new UpdateWrapper<>(); LambdaUpdateWrapper lambdaUpdateWrapper = updateWrapper.lambda(); // 使用 Lambda 表达式构建更新条件 lambdaUpdateWrapper.set(User::getName, "李四"); ``` -------------------------------- ### Create QueryWrapper using Wrappers Factory Source: https://baomidou.com/guides/wrapper Use the static Wrappers.query() factory method for concise QueryWrapper instantiation. Ensure proper parameter binding to prevent SQL injection. ```java // 创建 QueryWrapper QueryWrapper queryWrapper = Wrappers.query(); queryWrapper.eq("name", "张三"); ``` -------------------------------- ### Query with XML Configuration using Wrapper Source: https://baomidou.com/guides/wrapper Define a mapper method in XML to execute a query using a Wrapper, referencing the Wrapper as 'ew'. ```xml ``` -------------------------------- ### Get Lambda Wrapper from QueryWrapper Source: https://baomidou.com/guides/wrapper Obtain a LambdaQueryWrapper from a QueryWrapper to use lambda expressions for type-safe queries. Ensure QueryWrapper is initialized. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); LambdaQueryWrapper lambdaQueryWrapper = queryWrapper.lambda(); // 使用 Lambda 表达式构建查询条件 lambdaQueryWrapper.eq(User::getName, "张三"); ``` -------------------------------- ### Configure Multiple Data Sources Source: https://baomidou.com/guides/dynamic-datasource Define primary and secondary data sources in application.properties or application.yml. Use ENC() for encrypted sensitive information. ```yaml spring: datasource: dynamic: primary: master strict: false datasource: master: url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver slave_1: url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver slave_2: url: ENC(xxxxx) username: ENC(xxxxx) password: ENC(xxxxx) driver-class-name: com.mysql.jdbc.Driver ``` -------------------------------- ### LambdaQueryWrapper notLikeRight Example Source: https://baomidou.com/guides/wrapper Use LambdaQueryWrapper to exclude records that end with a specific string using lambda expressions. Ensures the value is a string. ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.notLikeRight(User::getName, "王"); ``` -------------------------------- ### Generated SQL for likeRight Source: https://baomidou.com/guides/wrapper Shows the SQL generated by both QueryWrapper and LambdaQueryWrapper for likeRight. ```sql -- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user WHERE name LIKE '王%' ``` -------------------------------- ### likeLeft Source: https://baomidou.com/guides/wrapper The `likeLeft` method is used for right fuzzy matching, matching records that start with the specified string. It appends '%' before the search value by default. ```APIDOC ## likeLeft ### Description Used for right fuzzy matching on string fields. By default, it appends '%' before the search value. ### Method Signature ```java likeLeft(R column, Object val) likeLeft(boolean condition, R column, Object val) ``` ### Parameters * `column` (R): The database field name or a field name using Lambda expression. * `val` (Object): The search value for the fuzzy match. * `condition` (boolean): A flag to control whether to apply this condition. ### Request Example **QueryWrapper**: ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.likeLeft("name", "王"); ``` **LambdaQueryWrapper**: ```java LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.likeLeft(User::getName, "王"); ``` ### Generated SQL ```sql SELECT * FROM user WHERE name LIKE '%王' ``` ### Notes * Ensure the `val` parameter is a string to avoid type conversion errors. * Use `like` or `likeRight` for full or left fuzzy matching respectively. ``` -------------------------------- ### Generate SQL for HAVING Clause Source: https://baomidou.com/guides/wrapper This SQL demonstrates the output of groupBy and having for both QueryWrapper and LambdaQueryWrapper. ```sql -- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user GROUP BY age HAVING sum(age) > 10 ``` -------------------------------- ### User Mapper Interface Source: https://baomidou.com/getting-started Create a UserMapper interface that extends MyBatis-Plus's BaseMapper to get basic CRUD operations for the User entity. ```java public interface UserMapper extends BaseMapper { } ``` -------------------------------- ### Create LambdaQueryWrapper using Wrappers Factory Source: https://baomidou.com/guides/wrapper Use the static Wrappers.lambdaQuery() factory method for concise LambdaQueryWrapper instantiation. Prefer lambda expressions for type safety. ```java // 创建 LambdaQueryWrapper LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery(); lambdaQueryWrapper.eq(User::getName, "张三"); ``` -------------------------------- ### Generated SQL for eq Source: https://baomidou.com/guides/wrapper Shows the SQL generated by the eq method for both regular and Lambda Wrappers. ```sql -- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user WHERE name = '老王' ``` -------------------------------- ### Configure Illegal SQL Interceptor with XML Source: https://baomidou.com/plugins/illegal-sql-intercept Configure the IllegalSQLInnerInterceptor using XML bean definitions. This approach is an alternative to Java-based configuration for setting up the interceptor. ```xml ``` -------------------------------- ### Generate SQL for Ascending Order Source: https://baomidou.com/guides/wrapper This SQL demonstrates the output of orderBy for both QueryWrapper and LambdaQueryWrapper with ascending order. ```sql -- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user ORDER BY id ASC, name ASC ``` -------------------------------- ### Set JsqlParser SQL Processing Method Source: https://baomidou.com/plugins Define custom processing logic for SQL statements before they are parsed by JsqlParser. This example shows how to set both multi-statement and single-statement parsing functions. ```java /* 3.5.6~3.5.11 请使用 JsqlParserGlobal.executorService 3.5.11+: JsqlParserGlobal.getExecutorService() 低于3.5.6的版本只能使用 CCJSqlParserUtil.parseStatements(sql); CCJSqlParserUtil.parse(sql) **/ static { JsqlParserGlobal.setParserMultiFunc((sql)-> { System.out.println("解析SQL:" + sql); return CCJSqlParserUtil.parseStatements(sql, JsqlParserGlobal.getExecutorService(), null); }); JsqlParserGlobal.setParserSingleFunc((sql)-> { System.out.println("解析SQL:" + sql); return CCJSqlParserUtil.parse(sql, JsqlParserGlobal.getExecutorService(), null); }); } ``` -------------------------------- ### Chain Update Wrapper Initialization Source: https://baomidou.com/guides/data-interface Initializes chain update wrappers for constructing database update operations fluently. Supports standard and lambda styles. ```Java UpdateChainWrapper update(); LambdaUpdateChainWrapper lambdaUpdate(); ``` -------------------------------- ### Configure Kotlin Maven Plugin for JVM Default Methods Source: https://baomidou.com/reference/question Configure the `kotlin-maven-plugin` with the `-Xjvm-default=all` argument to resolve issues with Kotlin calling default methods in interfaces. ```xml org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} -Xjsr305=strict -Xjvm-default=all ``` -------------------------------- ### Configure Optimistic Locker Plugin (Spring XML) Source: https://baomidou.com/plugins/optimistic-locker Configure the OptimisticLockerInnerInterceptor and MybatisPlusInterceptor beans in Spring XML for optimistic locking. ```xml ``` -------------------------------- ### Field Binding for Dictionary Mapping Source: https://baomidou.com/guides/advanced-features Use the @FieldBind annotation to map database values to display properties. This example shows how the 'sex' field (0/1) is mapped to 'sexText' ('男'/'女'). ```java @FieldBind(type = "user_sex", target = "sexText") private Integer sex; // 绑定显示属性,非表字典(排除) @TableField(exist = false) private String sexText; ``` -------------------------------- ### Configure MyBatis-Mate Data Sources Source: https://baomidou.com/guides/dynamic-datasource Define data sources for mybatis-mate using the 'mybatis-mate.sharding' configuration. Supports multiple database types and clustering. ```yaml mybatis-mate: sharding: primary: mysql datasource: mysql: - key: node1 ... - key: node2 cluster: slave ... postgres: - key: node1 ... ``` -------------------------------- ### Create UpdateWrapper using Wrappers Factory Source: https://baomidou.com/guides/wrapper Use the static Wrappers.update() factory method for concise UpdateWrapper instantiation. Ensure proper parameter binding to prevent SQL injection. ```java // 创建 UpdateWrapper UpdateWrapper updateWrapper = Wrappers.update(); updateWrapper.set("name", "李四"); ``` -------------------------------- ### Maven POM Resource Configuration for XML Files Source: https://baomidou.com/reference/question Configure the Maven build process to include XML files from the 'src/main/java' directory into the build output. This ensures that custom SQL XML files are available at runtime. ```xml src/main/java **/*.xml src/main/resources ``` -------------------------------- ### Configure MyBatis Plus to Return Instances for Empty Rows Source: https://baomidou.com/reference/question Set `return-instance-for-empty-row` to `true` in MyBatis Plus configuration to ensure that query results are never null, even if all columns are empty. ```yaml mybatis-plus: configuration: return-instance-for-empty-row: true ``` -------------------------------- ### Custom JsonBind Strategy Function Source: https://baomidou.com/guides/advanced-features Implement IJsonBindStrategy to define custom functions for binding virtual JSON properties. This example shows how to map status codes to text and fetch related data like role names. ```java @Component public class JsonBindStrategy implements IJsonBindStrategy { @Override public Map>> getStrategyFunctionMap() { return new HashMap>>(16) { { // 注入虚拟节点 put(Type.departmentRole, (obj) -> new HashMap(2) {{ User user = (User) obj; // 枚举类型转换 put("statusText", StatusEnum.get(user.getStatus()).getDesc()); // 可调用数据库查询角色信息 put("roleName", "经理"); }}); } }; } } ``` -------------------------------- ### Spring Boot Configuration for Pagination Plugin Source: https://baomidou.com/plugins Configure the MybatisPlusInterceptor with PaginationInnerInterceptor using Java configuration in a Spring Boot application. Ensure your mapper package is scanned. ```java @Configuration @MapperScan("scan.your.mapper.package") public class MybatisPlusConfig { /** * 添加分页插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); return interceptor; } } ``` -------------------------------- ### XML Configuration for Custom Pagination Method Source: https://baomidou.com/plugins/pagination XML configuration for a custom Mapper method that uses pagination. If the return type is IPage, the input IPage cannot be null. To temporarily disable pagination, set the size parameter of IPage to less than 0. ```xml ``` -------------------------------- ### Configure Dynamic Table Name Interceptor Source: https://baomidou.com/plugins/dynamic-table-name Add the DynamicTableNameInnerInterceptor to your MyBatis-Plus interceptor chain and define a table name handler. The handler receives the SQL and original table name, returning the modified table name. This example dynamically appends '_2018' or '_2019' based on a random number. ```java import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Map; import java.util.Random; @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor(); dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> { // 获取参数方法 Map paramMap = RequestDataHelper.getRequestData(); paramMap.forEach((k, v) -> System.err.println(k + "----" + v)); String year = "_2018"; int random = new Random().nextInt(10); if (random % 2 == 1) { year = "_2019"; } return tableName + year; }); interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor); return interceptor; } } ``` -------------------------------- ### Generated SQL for likeLeft Source: https://baomidou.com/guides/wrapper Shows the SQL generated by both QueryWrapper and LambdaQueryWrapper for likeLeft. ```sql -- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user WHERE name LIKE '%王' ``` -------------------------------- ### Spring Boot Configuration (application.yml) Source: https://baomidou.com/reference Configure MyBatis-Plus settings in a Spring Boot project using application.yml. This includes global and database configurations. ```yaml mybatis-plus: configuration: # MyBatis 配置 map-underscore-to-camel-case: true global-config: # 全局配置 db-config: # 数据库配置 id-type: auto ``` -------------------------------- ### keyMap: Query and Map Entities by Attribute Source: https://baomidou.com/guides/data-interface Use keyMap to query entities and return them as a Map where a specific attribute is the key and the entity is the value. Supports peek operations for side effects. ```java Map keyMap(LambdaQueryWrapper wrapper, SFunction sFunction, Consumer... peeks); ``` ```java Map keyMap(LambdaQueryWrapper wrapper, SFunction sFunction, boolean isParallel, Consumer... peeks); ``` ```java // 假设有一个 User 实体类和对应的 BaseMapper LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(User::getStatus, "active"); // 查询状态为 "active" 的用户 // 使用 keyMap 方法查询并封装结果 Map userMap = SimpleQuery.keyMap( queryWrapper, // 查询条件构造器 User::getUsername, // 使用用户名作为键 user -> System.out.println("Processing user: " + user.getUsername()) // 打印处理的用户名 ); // 遍历结果 for (Map.Entry entry : userMap.entrySet()) { System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()); } ``` -------------------------------- ### Basic Select Test with MyBatis-Plus Source: https://baomidou.com/getting-started A JUnit test class demonstrating how to use the injected UserMapper to select all users. The selectList method takes a null Wrapper for no conditions. ```java @SpringBootTest public class SampleTest { @Autowired private UserMapper userMapper; @Test public void testSelect() { System.out.println(("----- selectAll method test ------")); List userList = userMapper.selectList(null); Assert.isTrue(5 == userList.size(), ""); userList.forEach(System.out::println); } } ``` -------------------------------- ### Create LambdaUpdateWrapper using Wrappers Factory Source: https://baomidou.com/guides/wrapper Use the static Wrappers.lambdaUpdate() factory method for concise LambdaUpdateWrapper instantiation. Prefer lambda expressions for type safety. ```java // 创建 LambdaUpdateWrapper LambdaUpdateWrapper lambdaUpdateWrapper = Wrappers.lambdaUpdate(); lambdaUpdateWrapper.set(User::getName, "李四"); ``` -------------------------------- ### Select Fields with QueryWrapper Source: https://baomidou.com/guides/wrapper Specify fields to query using their names. This is for QueryWrapper. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("id", "name", "age"); ``` -------------------------------- ### Configure Kotlin Gradle for JVM Default Methods Source: https://baomidou.com/reference/question Configure Kotlin compilation in Gradle with `freeCompilerArgs = ['-Xjvm-default=all']` to address issues with calling default interface methods from Kotlin. ```gradle compileKotlin { kotlinOptions { freeCompilerArgs = ['-Xjvm-default=all'] } } ``` -------------------------------- ### MyBatis Configuration: checkConfigLocation Source: https://baomidou.com/reference Enable or disable checking for the existence of MyBatis XML files on startup. This is a Spring Boot specific setting. ```yaml mybatis-plus: check-config-location: true ``` -------------------------------- ### Conditional Query Construction with Wrapper Source: https://baomidou.com/guides/wrapper Use boolean parameters in Wrapper methods to conditionally include criteria in the SQL. If a parameter is not provided, the condition defaults to true. ```java queryWrapper.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age != null && age >= 0, Entity::getAge, age); ``` -------------------------------- ### Console Output of User Data Source: https://baomidou.com/getting-started The expected console output after running the testSelect method, showing the details of all users retrieved from the database. ```text User(id=1, name=Jone, age=18, email=test1@baomidou.com) User(id=2, name=Jack, age=20, email=test2@baomidou.com) User(id=3, name=Tom, age=28, email=test3@baomidou.com) User(id=4, name=Sandy, age=21, email=test4@baomidou.com) User(id=5, name=Billie, age=24, email=test5@baomidou.com) ``` -------------------------------- ### Executing SQL Scripts with ShardingKey Change Source: https://baomidou.com/guides/advanced-features This snippet demonstrates how to execute SQL scripts, including DELETE and INSERT statements, after changing the sharding key to a specific MySQL slave. ```java // 切换到 mysql 从库,执行 SQL 脚本 ShardingKey.change("mysqlt2"); ddlScript.run(new StringReader("DELETE FROM user;\n" + "INSERT INTO user (id, username, password, sex, email) VALUES\n" + "(20, 'Duo', '123456', 0, 'Duo@baomidou.com');")); ``` -------------------------------- ### Implement MetaObjectHandler for Auto-Fill Logic (Java) Source: https://baomidou.com/guides/auto-fill-field Implement the MetaObjectHandler interface and override insertFill and updateFill methods to define custom logic for populating fields. Ensure the class is managed by Spring. ```java // java example @Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { log.info("开始插入填充..."); this.strictInsertFill(metaObject, "createUserId", Long.class, 123456L) this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); } @Override public void updateFill(MetaObject metaObject) { log.info("开始更新填充..."); this.strictInsertFill(metaObject, "updateUserId", Long.class, 123456L) this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); } } ``` -------------------------------- ### Basic QueryWrapper Usage Source: https://baomidou.com/guides/wrapper Use QueryWrapper for standard SQL query construction. The apply method can be used to append SQL fragments. ```java QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.apply("id = 1"); ``` -------------------------------- ### Generate SQL for Descending Order Source: https://baomidou.com/guides/wrapper This SQL demonstrates the output of orderByDesc for both QueryWrapper and LambdaQueryWrapper. ```sql -- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同 SELECT * FROM user ORDER BY id DESC, name DESC ``` -------------------------------- ### Manual Data Comparison for Auditing Source: https://baomidou.com/guides/advanced-features Manually compare two objects for data auditing purposes using DataAuditor.compare. ```java DataAuditor.compare(obj1, obj2); ```