### Example Query Result Output Source: https://mybatis-flex.com/zh/base/relations-query.html Example of the final mapped `UserVO` objects after the join query execution. ```txt UserVO{userId='1', userName='admin', roleList=[Role{roleId=1, roleKey='admin', roleName='超级管理员'}]} UserVO{userId='2', userName='ry', roleList=[Role{roleId=2, roleKey='common', roleName='普通角色'}]} UserVO{userId='3', userName='test', roleList=[Role{roleId=1, roleKey='admin', roleName='超级管理员'}, Role{roleId=2, roleKey='common', roleName='普通角色'}]} ``` -------------------------------- ### EnjoyTemplate Implementation Example Source: https://mybatis-flex.com/zh/others/codegen.html Code example for the built-in EnjoyTemplate, demonstrating how to configure a custom template engine for code generation. ```java public class EnjoyTemplate implements ITemplate { private Engine engine; public EnjoyTemplate() { Engine engine = Engine.use(engineName); if (engine == null) { engine = Engine.create(engineName, e -> { e.addSharedStaticMethod(StringUtil.class); e.setSourceFactory(new FileAndClassPathSourceFactory()); }); } this.engine = engine; // 以下配置将支持 user.girl 表达式去调用 user 对象的 boolean isGirl() 方法 Engine.addFieldGetterToFirst(new FieldGetters.IsMethodFieldGetter()); } @Override public void generate(Map params, String templateFilePath, File generateFile) { if (!generateFile.getParentFile().exists() && !generateFile.getParentFile().mkdirs()) { throw new IllegalStateException("Can not mkdirs by dir: " + generateFile.getParentFile()); } // 开始生成文件 try (FileOutputStream fileOutputStream = new FileOutputStream(generateFile)) { engine.getTemplate(templateFilePath).render(params, fileOutputStream); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### SELECT * Example Source: https://mybatis-flex.com/zh/base/querywrapper.html Examples demonstrating how to use QueryWrapper to select all columns or specific columns from a table. ```java QueryWrapper query1 = new QueryWrapper(); query1.select(ACCOUNT.ID, ACCOUNT.USER_NAME) .from(ACCOUNT); QueryWrapper query2 = new QueryWrapper(); query2.select().from(ACCOUNT); ``` -------------------------------- ### SELECT ... AS Example Source: https://mybatis-flex.com/zh/base/querywrapper.html An example showing how to use QueryWrapper to select columns with aliases. ```java QueryWrapper query = new QueryWrapper() .select( ACCOUNT.ID.as("accountId") , ACCOUNT.USER_NAME) .from(ACCOUNT.as("a")); ``` -------------------------------- ### MyBatis-Flex Banner Example Source: https://mybatis-flex.com/zh/faq.html This is the expected Banner information printed by MyBatis-Flex during startup. ```text __ __ _ _ _ _____ _ | \/ |_ _| |__ __ _| |_(_)___ | ___| | _____ __ | |\/| | | | | '_ \ / _` | __| / __| | |_ | |/ _ \ \/ / | | | | |_| | |_) | (_| | |_| \__ \ | _| | | __/> < |_| |_|\__, |_.__/ \__,_|\__|_|___/ |_| |_|\___/_/\_\ |___/ v1.5.4 https://mybatis-flex.com ``` -------------------------------- ### Query Top-Level Menus Source: https://mybatis-flex.com/zh/base/relations-query.html Example of querying top-level menus using QueryWrapper and relation mapping. ```java QueryWrapper qw = QueryWrapper.create(); qw.where(MENU.PARENT_ID.eq(0)); List menus = menuMapper.selectListWithRelationsByQuery(qw); System.out.println(JSON.toJSONString(menus)); ``` -------------------------------- ### SELECT Multiple Tables Example Source: https://mybatis-flex.com/zh/base/querywrapper.html An example demonstrating how to use QueryWrapper to select data from multiple tables with join conditions. ```java QueryWrapper query = new QueryWrapper() .select( ACCOUNT.ID , ACCOUNT.USER_NAME , ARTICLE.ID.as("articleId") , ARTICLE.TITLE) .from(ACCOUNT.as("a"), ARTICLE.as("b")) .where(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID)); ``` -------------------------------- ### With Select Example 2 Source: https://mybatis-flex.com/zh/base/querywrapper.html Shows creating a CTE with specified columns and values using `with().asValues()`. ```java QueryWrapper query = new QueryWrapper() .with("xxx", "id", "name").asValues( Arrays.asList("a", "b"), union( select().from(ARTICLE).where(ARTICLE.ID.ge(200)) ) ) .from(ACCOUNT) .where(ACCOUNT.SEX.eq(1)); System.out.println(query.toSQL()); ``` ```sql WITH xxx(id, name) AS (VALUES (a, b) UNION (SELECT * FROM `tb_article` WHERE `id` >= 200)) SELECT * FROM `tb_account` WHERE `sex` = 1 ``` -------------------------------- ### Where Clause Example Source: https://mybatis-flex.com/zh/base/querywrapper.html Demonstrates basic usage of the `where()` and `and()` clauses for filtering. ```java QueryWrapper queryWrapper=QueryWrapper.create() .select() .from(ACCOUNT) .where(ACCOUNT.ID.ge(100)) .and(ACCOUNT.USER_NAME.like("michael")); ``` ```sql SELECT * FROM tb_account WHERE id >= ? AND user_name LIKE ? ``` -------------------------------- ### union, union all Source: https://mybatis-flex.com/zh/base/querywrapper.html Example of using union and unionAll with QueryWrapper. ```java QueryWrapper query = new QueryWrapper() .select(ACCOUNT.ID) .from(ACCOUNT) .orderBy(ACCOUNT.ID.desc()) .union(select(ARTICLE.ID).from(ARTICLE)) .unionAll(select(ARTICLE.ID).from(ARTICLE)); ``` -------------------------------- ### With Select Example 1 Source: https://mybatis-flex.com/zh/base/querywrapper.html Illustrates creating a Common Table Expression (CTE) using `with().asSelect()`. ```java QueryWrapper query = new QueryWrapper() .with("CTE").asSelect( select().from(ARTICLE).where(ARTICLE.ID.ge(100)) ) .select() .from(ACCOUNT) .where(ACCOUNT.SEX.eq(1)); System.out.println(query.toSQL()); ``` ```sql WITH CTE AS (SELECT * FROM `tb_article` WHERE `id` >= 100) SELECT * FROM `tb_account` WHERE `sex` = 1 ``` -------------------------------- ### Column Calculation Example 1: Addition Source: https://mybatis-flex.com/zh/base/querywrapper.html Illustrates how to perform addition on a column and alias the result. ```java QueryWrapper query = new QueryWrapper() .select(ACCOUNT.ID.add(100).as("x100")) .from(ACCOUNT); String sql = query.toSQL(); ``` -------------------------------- ### Select Case When Example 2 Source: https://mybatis-flex.com/zh/base/querywrapper.html Demonstrates another `case_()` usage with a direct value comparison. ```java QueryWrapper queryWrapper = QueryWrapper.create() .select( ACCOUNT.ALL_COLUMNS, case_(ACCOUNT.ID) .when(100).then(100) .when(200).then(200) .else_(300).end().as("result") ) .from(ACCOUNT) .where(ACCOUNT.USER_NAME.like("michael")); ``` ```sql SELECT *, (CASE `id` WHEN 100 THEN 100 WHEN 200 THEN 200 ELSE 300 END) AS `result` FROM `tb_account` WHERE `user_name` LIKE ? ``` -------------------------------- ### Column Calculation Example 2: Sum and Multiply Source: https://mybatis-flex.com/zh/base/querywrapper.html Demonstrates using aggregate functions like SUM with column multiplication. ```java QueryWrapper query = new QueryWrapper() .select(sum(ACCOUNT.ID.multiply(ACCOUNT.AGE)).as("total_x")) .from(ACCOUNT); ``` -------------------------------- ### Code Generation Example Source: https://mybatis-flex.com/zh/others/codegen.html Write a class with a main method to configure the data source and generate code. ```java public class Codegen { public static void main(String[] args) { //配置数据源 HikariDataSource dataSource = new HikariDataSource(); dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/your-database?characterEncoding=utf-8"); dataSource.setUsername("root"); dataSource.setPassword("******"); //创建配置内容,两种风格都可以。 GlobalConfig globalConfig = createGlobalConfigUseStyle1(); //GlobalConfig globalConfig = createGlobalConfigUseStyle2(); //通过 datasource 和 globalConfig 创建代码生成器 Generator generator = new Generator(dataSource, globalConfig); //生成代码 generator.generate(); } public static GlobalConfig createGlobalConfigUseStyle1() { //创建配置内容 GlobalConfig globalConfig = new GlobalConfig(); //设置根包 globalConfig.setBasePackage("com.test"); //设置表前缀和只生成哪些表 globalConfig.setTablePrefix("tb_"); globalConfig.setGenerateTable("tb_account", "tb_account_session"); //设置生成 entity 并启用 Lombok globalConfig.setEntityGenerateEnable(true); globalConfig.setEntityWithLombok(true); //设置项目的JDK版本,项目的JDK为14及以上时建议设置该项,小于14则可以不设置 globalConfig.setEntityJdkVersion(17); //设置生成 mapper globalConfig.setMapperGenerateEnable(true); //可以单独配置某个列 ColumnConfig columnConfig = new ColumnConfig(); columnConfig.setColumnName("tenant_id"); columnConfig.setLarge(true); columnConfig.setVersion(true); globalConfig.setColumnConfig("tb_account", columnConfig); return globalConfig; } public static GlobalConfig createGlobalConfigUseStyle2() { //创建配置内容 GlobalConfig globalConfig = new GlobalConfig(); //设置根包 globalConfig.getPackageConfig() .setBasePackage("com.test"); //设置表前缀和只生成哪些表,setGenerateTable 未配置时,生成所有表 globalConfig.getStrategyConfig() .setTablePrefix("tb_") .setGenerateTable("tb_account", "tb_account_session"); //设置生成 entity 并启用 Lombok globalConfig.enableEntity() .setWithLombok(true) .setJdkVersion(17); //设置生成 mapper globalConfig.enableMapper(); //可以单独配置某个列 ColumnConfig columnConfig = new ColumnConfig(); columnConfig.setColumnName("tenant_id"); columnConfig.setLarge(true); columnConfig.setVersion(true); globalConfig.getStrategyConfig() .setColumnConfig("tb_account", columnConfig); return globalConfig; } } ``` -------------------------------- ### Column Calculation Example 3: Nested Addition Source: https://mybatis-flex.com/zh/base/querywrapper.html Shows how to perform nested addition operations on columns. ```java QueryWrapper query = new QueryWrapper() .select(ACCOUNT.ID.add(ACCOUNT.AGE.add(100)).as("x100")) .from(ACCOUNT); String sql = query.toSQL(); ``` -------------------------------- ### Maven Dependency for seata-spring-boot-starter Source: https://mybatis-flex.com/zh/core/tx.html Example Maven dependency for integrating seata-spring-boot-starter into a Spring Boot project. ```xml io.seata seata-spring-boot-starter 1.7.0 ``` -------------------------------- ### ServiceImpl Generation Configuration Source: https://mybatis-flex.com/zh/others/codegen.html Example of configuring ServiceImpl generation, including setting class prefixes and suffixes, and superclass. ```java globalConfig.getServiceImplConfig() .setClassPrefix("My") .setClassSuffix("ServiceImpl") .setSuperClass(ServiceImpl.class); ``` -------------------------------- ### Service Generation Configuration Source: https://mybatis-flex.com/zh/others/codegen.html Example of configuring service generation, including setting class prefixes and suffixes, and superclass. ```java globalConfig.getServiceConfig() .setClassPrefix("My") .setClassSuffix("Service") .setSuperClass(IService.class); ``` -------------------------------- ### 实体类不在同一包下的辅助类生成 Source: https://mybatis-flex.com/zh/others/apt.html 当实体类不在同一包时,辅助类会在对应包下生成。如果启用了 `processor.allInTables.enable`,`Tables` 文件会生成在最后一个包中。推荐设置 `Tables` 文件的位置。 ```properties processor.allInTables.enable=true processor.allInTables.package=com.example.entity.table ``` -------------------------------- ### Seata Global Transactional Annotation Source: https://mybatis-flex.com/zh/core/tx.html Example of starting a Seata distributed transaction using the @GlobalTransactional annotation. ```java import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import com.seata.core.context.RootContext; import com.seata.spring.annotation.GlobalTransactional; public class PurchaseService { private static final Log LOGGER = LogFactory.getLog(PurchaseService.class); private StockClient stockClient; private OrderClient orderClient; @GlobalTransactional public void purchase(String userId, String commodityCode, int orderCount) { LOGGER.info("purchase begin ... xid: " + RootContext.getXID()); stockClient.deduct(commodityCode, orderCount); orderClient.create(userId, commodityCode, orderCount); } } ``` -------------------------------- ### Using saveOpt for Callbacks Source: https://mybatis-flex.com/zh/base/active-record.html Example demonstrating the use of saveOpt() to get the saved entity with its ID after insertion, handling potential failures. ```java // 插入成功之后返回主键信息 Account.create() .setUserName("张三") .setAge(18) .setBirthday(new Date()) .saveOpt() .orElseThrow(RuntimeException::new) // 保存失败抛出异常 .getId(); ``` -------------------------------- ### Maven 编译命令 Source: https://mybatis-flex.com/zh/others/apt.html 执行 maven 编译命令可以自动生成 APT 代码。 ```bash mvn clean package ``` -------------------------------- ### 配置 MybatisFlexBootstrap Source: https://mybatis-flex.com/zh/intro/use-in-kotlin.html 使用 DSL 和运算符重载快速配置 MybatisFlexBootstrap 实例。注意此方式不适用于 SpringBoot 环境。 ```kotlin runFlex { // 配置数据源 相当于 setDataSource(dataSource) +dataSource // 配置Mapper 相当于 addMapper(AccountMapper::class.java) +AccountMapper::class // 配置日志输出 相当于 setLogImpl(StdOutImpl::class.java) logImpl = StdOutImpl::class } ``` -------------------------------- ### limit... offset Source: https://mybatis-flex.com/zh/base/querywrapper.html Example of using limit and offset with QueryWrapper, with database-specific SQL examples. ```java QueryWrapper queryWrapper = QueryWrapper.create() .select() .from(ACCOUNT) .orderBy(ACCOUNT.ID.desc()) .limit(10) .offset(20); ``` -------------------------------- ### Gradle 编译配置 Source: https://mybatis-flex.com/zh/others/apt.html 使用 Gradle 编译时,需要在 `dependencies` 中添加 `annotationProcessor` 配置。 ```gradle dependencies { ... annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.11.7' } ``` -------------------------------- ### 使用 prepareAuth 实现数据权限 Source: https://mybatis-flex.com/zh/core/data-permission.html 通过重写 prepareAuth 方法处理 QueryWrapper 或 SQL 语句以添加权限条件。 ```java public class AuthDialectImpl extends CommonsDialectImpl { @Override public void prepareAuth(QueryWrapper queryWrapper, OperateType operateType) { List queryTables = CPI.getQueryTables(queryWrapper); if (queryTables == null || queryTables.isEmpty()) { return; } for (QueryTable queryTable : queryTables) { if (PROJECT.getTableName().equals(queryTable.getName())) { queryWrapper.and(PROJECT.INSERT_USER_ID.eq(1)); } } super.prepareAuth(queryWrapper, operateType); } @Override public void prepareAuth(String schema, String tableName, StringBuilder sql, OperateType operateType) { if (PROJECT.getTableName().equals(tableName)) { sql.append(AND).append(wrap("insert_user_id")).append(EQUALS).append(1); } super.prepareAuth(schema, tableName, sql, operateType); } @Override public void prepareAuth(TableInfo tableInfo, StringBuilder sql, OperateType operateType) { if (PROJECT.getTableName().equals(tableInfo.getTableName())) { sql.append(AND).append(wrap("insert_user_id")).append(EQUALS).append(1); } super.prepareAuth(tableInfo, sql, operateType); } } ``` -------------------------------- ### Complete Cacheable Methods Example Source: https://mybatis-flex.com/zh/core/data-cache.html Comprehensive example of AccountServiceImpl demonstrating various cacheable and cache-evicting methods. ```java @Service @CacheConfig(cacheNames = "account") public class AccountServiceImpl extends CacheableServiceImpl { @Override @CacheEvict(allEntries = true) public boolean remove(QueryWrapper query) { return super.remove(query); } @Override @CacheEvict(key = "#id") public boolean removeById(Serializable id) { return super.removeById(id); } @Override @CacheEvict(allEntries = true) public boolean removeByIds(Collection ids) { return super.removeByIds(ids); } // 根据查询条件更新时,实体类主键可能为 null。 @Override @CacheEvict(allEntries = true) public boolean update(Account entity, QueryWrapper query) { return super.update(entity, query); } @Override @CacheEvict(key = "#entity.id") public boolean updateById(Account entity, boolean ignoreNulls) { return super.updateById(entity, ignoreNulls); } @Override @CacheEvict(allEntries = true) public boolean updateBatch(Collection entities, int batchSize) { return super.updateBatch(entities, batchSize); } @Override @Cacheable(key = "#id") public Account getById(Serializable id) { return super.getById(id); } @Override @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") public Account getOne(QueryWrapper query) { return super.getOne(query); } @Override @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") public R getOneAs(QueryWrapper query, Class asType) { return super.getOneAs(query, asType); } @Override @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") public List list(QueryWrapper query) { return super.list(query); } @Override @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") public List listAs(QueryWrapper query, Class asType) { return super.listAs(query, asType); } // 无法通过注解进行缓存操作 @Override @Deprecated public List listByIds(Collection ids) { return super.listByIds(ids); } @Override @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") public long count(QueryWrapper query) { return super.count(query); } @Override @Cacheable(key = "#root.methodName + ':' + #page.getPageSize() + ':' + #page.getPageNumber() + ':' + #query.toSQL()") public Page pageAs(Page page, QueryWrapper query, Class asType) { return super.pageAs(page, query, asType); } } ``` -------------------------------- ### 配置大字段标识 Source: https://mybatis-flex.com/zh/core/column.html 使用 isLarge 属性标记大字段,使其在 APT 生成的 DEFAULT_COLUMNS 中被排除,优化查询性能。 ```java @Table("tb_article") public class Article { @Id(keyType = KeyType.Auto) private Long id; private String title; @Column(isLarge = true) private String content; @Column(onInsertValue = "now()") private Date created; @Column(onUpdateValue = "now()", onInsertValue = "now()") private Date modified; } ``` ```java public class Tables { public static final ArticleTableDef ARTICLE = new ArticleTableDef("tb_article"); public static class ArticleTableDef extends TableDef { public QueryColumn ID = new QueryColumn(this, "id"); public QueryColumn TITLE = new QueryColumn(this, "title"); public QueryColumn CONTENT = new QueryColumn(this, "content"); public QueryColumn CREATED = new QueryColumn(this, "created"); public QueryColumn MODIFIED = new QueryColumn(this, "modified"); //在 DEFAULT_COLUMNS 中是没有 content 字段。 public QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{ID, TITLE, CREATED, MODIFIED}; public QueryColumn ALL_COLUMNS = new QueryColumn("*"); } } ``` ```java QueryWrapper.create() .select(ARTICLE.DEFAULT_COLUMNS) //使用的是 DEFAULT_COLUMNS .from(ARTICLE); ``` -------------------------------- ### Entity Superclass Factory Example Source: https://mybatis-flex.com/zh/others/codegen.html Example demonstrating the use of setEntitySuperClassFactory to dynamically set the superclass for entities based on the table. ```java globalConfig.setEntitySuperClassFactory(table -> { // 在这里,可以通过 table 来指定对应 SuperClass // 返回 null,则表示不需要设置父类 return null; }); ``` -------------------------------- ### 自定义 APT 代码生成路径 Source: https://mybatis-flex.com/zh/others/apt.html 配置 `processor.genPath` 来自定义 APT 代码生成路径。 ```properties processor.genPath=your-path ``` -------------------------------- ### Code Generator Cannot Get Comments Source: https://mybatis-flex.com/zh/faq.html For MySQL databases, if the database version is too low, you might not get comments. To resolve this, add the parameter 'useInformationSchema=true' to the jdbcUrl. For Oracle, add 'remarksReporting=true'. ```string jdbc:mysql://127.0.0.1:3306/mybatis-flex?characterEncoding=UTF-8&useInformationSchema=true ``` ```string jdbc:oracle:thin:@localhost:1521:orcl?remarksReporting=true ``` -------------------------------- ### Implement MyBatisFlexCustomizer for Initialization Source: https://mybatis-flex.com/zh/base/mybatis-flex-customizer.html Implement the MyBatisFlexCustomizer interface in a @Configuration class to perform initialization configurations for MyBatis-Flex. This is useful for setting up global configurations, custom primary key generators, multi-tenancy, dynamic table names, and more. ```java import org.springframework.context.annotation.Configuration; import com.mybatisflex.core.config.FlexGlobalConfig; import com.mybatisflex.core.mybatis.MyBatisFlexCustomizer; @Configuration public class MyBatisFlexConfiguration implements MyBatisFlexCustomizer { @Override public void customize(FlexGlobalConfig globalConfig) { // We can perform a series of initialization configurations here } } ``` -------------------------------- ### Db.tx() Code Example Source: https://mybatis-flex.com/zh/core/tx.html This example demonstrates the basic usage of the Db.tx() method. The provided Supplier contains the transactional operations. If the Supplier returns true, the transaction is committed; otherwise (if it returns null, false, or throws an exception), the transaction is rolled back. ```java Db.tx(() -> { //进行事务操作 return true; }); ``` -------------------------------- ### join self Source: https://mybatis-flex.com/zh/base/querywrapper.html Example of joining a table to itself using QueryWrapper. ```java AccountTableDef a1 = ACCOUNT.as("a1"); AccountTableDef a2 = ACCOUNT.as("a2"); ArticleTableDef ar = ARTICLE.as("ar"); QueryWrapper queryWrapper = new QueryWrapper() .select(ar.CONTENT, a1.ID, a2.AGE) .from(ar) .leftJoin(a1).on(a1.ID.eq(ar.ACCOUNT_ID)) .leftJoin(a2).on(a2.ID.eq(ar.ACCOUNT_ID)); ``` -------------------------------- ### Using SQL Hints Source: https://mybatis-flex.com/zh/base/querywrapper.html Explains and demonstrates the use of SQL hints (e.g., `INDEX_DESC`) to influence query execution plans. ```java QueryWrapper queryWrapper=QueryWrapper.create() .select().hint("INDEX_DESC") .from(ACCOUNT) .orderBy(ACCOUNT.AGE.asc(), ACCOUNT.USER_NAME.desc().nullsLast()); ``` -------------------------------- ### APT 开启 Mapper 生成 Source: https://mybatis-flex.com/zh/others/apt.html 配置 `processor.mapper.generateEnable=true` 来开启 Mapper 的自动生成功能。 ```properties processor.mapper.generateEnable=true ``` -------------------------------- ### join select Source: https://mybatis-flex.com/zh/base/querywrapper.html Example of joining with a subquery using QueryWrapper. ```java QueryWrapper queryWrapper = QueryWrapper.create() .select() .from(ACCOUNT) .leftJoin( select().from(ARTICLE).where(ARTICLE.ID.ge(100)) ).as("a").on( ACCOUNT.ID.eq(raw("a.id")) ) .where(ACCOUNT.AGE.ge(10)); ``` -------------------------------- ### 自定义 TableDef 字段风格 Source: https://mybatis-flex.com/zh/others/apt.html 配置 `processor.tableDef.propertiesNameStyle` 来修改 TableDef 生成的字段风格。 ```properties #upperCase, lowerCase, upperCamelCase, lowerCamelCase processor.tableDef.propertiesNameStyle=upperCase ``` -------------------------------- ### 自定义 Tables 类名和包名 Source: https://mybatis-flex.com/zh/others/apt.html 配置 `processor.allInTables.enable`、`processor.allInTables.package`、`processor.allInTables.className` 来自定义生成的 Tables 类名和包名。 ```properties processor.allInTables.enable=true processor.allInTables.package=com.your-package processor.allInTables.className=your-class-name ``` -------------------------------- ### Nested Transaction Example Source: https://mybatis-flex.com/zh/core/tx.html This example illustrates how to implement nested transactions using Db.tx(). The outer Db.tx() call wraps an inner Db.tx() call. By default, nested transactions behave like the REQUIRED propagation, meaning they join an existing transaction if one is present, or create a new one if not. ```java Db.tx(() -> { //进行事务操作 boolean success = Db.tx(() -> { //另一个事务的操作 return true; }); return true; }); ``` -------------------------------- ### Spring Boot 配置注册方言 Source: https://mybatis-flex.com/zh/core/data-permission.html 在 Spring Boot 项目中通过 MyBatisFlexCustomizer 注册方言。 ```java @Configuration public class MybatisFlexConfig implements MyBatisFlexCustomizer { @Override public void customize(FlexGlobalConfig flexGlobalConfig) { // 注册查询权限监听方言 DialectFactory.registerDialect(DbType.MYSQL, new AuthDialectImpl()); } } ``` -------------------------------- ### Cursor Query Example Source: https://mybatis-flex.com/zh/base/query.html For processing large datasets, use cursor queries to prevent memory leaks. This example demonstrates fetching accounts using a cursor within a transaction. Cursor queries fetch data one record at a time during iteration, and must be executed within a transaction to maintain the database connection. ```java Cursor selectCursorByQuery(QueryWrapper queryWrapper); ``` ```java Db.tx(() -> { Cursor accounts = accountMapper.selectCursorByQuery(query); for (Account account : accounts) { System.out.println(account); } return true; }); ``` -------------------------------- ### Inserting an Article Source: https://mybatis-flex.com/zh/core/multi-tenancy.html Example of inserting an Article, demonstrating how tenantId is handled. ```java Article article = new Article(); article.setTenantId(100); articleMapper.insert(article); ``` -------------------------------- ### 配置数据源解密器 Source: https://mybatis-flex.com/zh/core/datasource-encryption.html 通过 DataSourceManager 设置解密逻辑,必须在 MybatisFlexBootstrap 初始化之前调用。 ```java DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/flex_test"); dataSource.setUsername("root123"); // 真实的账号应该是 root dataSource.setPassword("123456---0000"); // 真实的密码应该是 123456 //配置数据源解密器:DataSourceDecipher DataSourceManager.setDecipher(new DataSourceDecipher() { @Override public String decrypt(DataSourceProperty property, String value) { //解密用户名,通过编码支持任意加密方式的解密 if (property == DataSourceProperty.USERNAME) { return value.substring(0, 4); } //解密密码 else if (property == DataSourceProperty.PASSWORD) { return value.substring(0, 6); } return value; } }); MybatisFlexBootstrap.getInstance() .setDataSource(dataSource) .addMapper(TenantAccountMapper.class) .start(); List rowList = Db.selectAll("tb_account"); RowUtil.printPretty(rowList); ``` -------------------------------- ### MyBatis-Plus Data Update Source: https://mybatis-flex.com/zh/intro/benchmark.html Example of updating data using MyBatis-Plus. ```java PlusAccount plusAccount = new PlusAccount(); plusAccount.setUserName("testInsert" + i); plusAccount.setNickname("testInsert" + i); plusAccount.addOption("key1", "value1"); plusAccount.addOption("key2", "value2"); plusAccount.addOption("key3", "value3"); plusAccount.addOption("key4", "value4"); plusAccount.addOption("key5", "value5"); LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.ge(PlusAccount::getId, 9000); updateWrapper.le(PlusAccount::getId, 9100); updateWrapper.like(PlusAccount::getUserName, "admin"); updateWrapper.like(PlusAccount::getNickname, "admin"); mapper.update(plusAccount, lambdaUpdateWrapper); ``` -------------------------------- ### MyBatis-Flex Data Update Source: https://mybatis-flex.com/zh/intro/benchmark.html Example of updating data using MyBatis-Flex. ```java FlexAccount flexAccount = new FlexAccount(); flexAccount.setUserName("testInsert" + i); flexAccount.setNickname("testInsert" + i); flexAccount.addOption("key1", "value1"); flexAccount.addOption("key2", "value2"); flexAccount.addOption("key3", "value3"); flexAccount.addOption("key4", "value4"); flexAccount.addOption("key5", "value5"); QueryWrapper queryWrapper = QueryWrapper.create() .where(FLEX_ACCOUNT.ID.ge(9200)) .and(FLEX_ACCOUNT.ID.le(9300)) .and(FLEX_ACCOUNT.USER_NAME.like("admin")) .and(FLEX_ACCOUNT.NICKNAME.like("admin")); mapper.updateByQuery(flexAccount, queryWrapper); ``` -------------------------------- ### APT 过滤 Entity 后缀 Source: https://mybatis-flex.com/zh/others/apt.html 配置 `processor.tableDef.ignoreEntitySuffixes` 来过滤 Entity 的通用后缀。 ```properties processor.tableDef.ignoreEntitySuffixes=Model, Dto ``` -------------------------------- ### MyBatis-Flex YAML Configuration Source: https://mybatis-flex.com/zh/base/configuration.html Example of MyBatis-Flex configuration in a SpringBoot or Solon application's YAML file. This section covers various aspects like data sources, global configurations, and admin settings. ```yaml mybatis-flex: #...... datasource: #...... configuration: #...... global-config: #...... admin-config: #...... seata-config: #...... ``` -------------------------------- ### Advanced UpdateWrapper Usage Source: https://mybatis-flex.com/zh/base/add-delete-update.html Advanced examples of using UpdateWrapper for complex field updates. ```java Account account = UpdateEntity.of(Account.class, 100); account.setUserName("Michael"); // 通过 UpdateWrapper 操作 account 数据 UpdateWrapper wrapper = UpdateWrapper.of(account); wrapper.set(ACCOUNT.AGE, ACCOUNT.AGE.add(1)); accountMapper.update(account); ``` ```sql update tb_account set user_name = "michael", age = age + 1 where id = 100 ``` ```java Account account = UpdateEntity.of(Account.class, 100); account.setUserName("Michael"); // 通过 UpdateWrapper 操作 account 数据 UpdateWrapper wrapper = UpdateWrapper.of(account); wrapper.set(ACCOUNT.AGE, select().from(...)); accountMapper.update(account); ``` ```sql update tb_account set user_name = "michael", age = (select ... from ... ) where id = 100 ``` -------------------------------- ### 自定义 Mapper 父类 Source: https://mybatis-flex.com/zh/others/apt.html 配置 `processor.mapper.baseClass` 来自定义 Mapper 的父类。 ```properties processor.mapper.baseClass=com.domain.mapper.MyBaseMapper ``` -------------------------------- ### Multi-Datasource Transaction Example Source: https://mybatis-flex.com/zh/core/tx.html This example shows how multiple data sources can be managed within a single @Transactional annotation. Even though operations are performed on different data sources (ds1 and ds2), they are part of the same transaction. If an exception occurs (like division by zero), all operations within that transaction will be rolled back. ```java @Transactional public void doSomething(){ try{ DataSourceKey.use("ds1"); Db.updateBySql("update .... "); }finally{ DataSourceKey.clear() } try{ DataSourceKey.use("ds2"); Db.updateBySql("update ..."); }finally{ DataSourceKey.clear(); } //抛出异常 int x = 1/0; } ``` -------------------------------- ### join on multiple conditions Source: https://mybatis-flex.com/zh/base/querywrapper.html Example of joining with multiple conditions using QueryWrapper. ```java QueryWrapper queryWrapper = QueryWrapper.create() .select() .from(ACCOUNT) .leftJoin(ARTICLE).on( ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID).and(ACCOUNT.AGE.eq(18)) ) .where(ACCOUNT.AGE.ge(10)); ``` -------------------------------- ### Excluding SpringDataWebAutoConfiguration Source: https://mybatis-flex.com/zh/faq.html Example of excluding SpringDataWebAutoConfiguration to resolve warnings with spring-data integration. ```java @SpringBootApplication(exclude = SpringDataWebAutoConfiguration.class) public class SampleApplication {} ``` -------------------------------- ### 默认 TableDef 生成 Source: https://mybatis-flex.com/zh/others/apt.html 默认情况下 APT 生成的 TableDef 内容示例。 ```java public class AccountTableDef extends TableDef { public static final AccountTableDef ACCOUNT = new AccountTableDef("", "tb_account"); public QueryColumn ID = new QueryColumn(this, "id"); public QueryColumn USER_NAME = new QueryColumn(this, "user_name"); public QueryColumn ALL_COLUMNS = new QueryColumn(this, "*"); public QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{ID, USER_NAME}; public AccountTableDef(String schema, String tableName) { super(schema, tableName); } } ``` -------------------------------- ### Gradle 插件应用 (Kotlin) Source: https://mybatis-flex.com/zh/others/kapt.html 在 Gradle 项目中应用 kotlin-kapt 插件,并注意版本一致性。 ```kotlin plugins { // 如果正在使用 SpringBoot,请保持 kapt 插件版本与 Spring 插件、kotlin JVM 插件一致 // 如你的插件版本是(如果项目是使用 Spring Initializr 生成的话,是会自带下面两个插件): // kotlin("jvm") version "1.9.20" <- 注意版本 // kotlin("plugin.spring") version "1.9.20" <- 注意版本 // 那么你的 kapt 版本也需要与其一致,否则将会改变项目使用的 Kotlin 版本,可能会引发兼容性问题 kotlin("kapt") version "1.9.20" } ``` -------------------------------- ### Multi-Table Query 1 (Fluent-MyBatis) Source: https://mybatis-flex.com/zh/intro/comparison.html Example of a join query using Fluent-MyBatis. ```java StudentQuery leftQuery = new StudentQuery("a1").selectAll() .where.age().eq(34) .end(); HomeAddressQuery rightQuery = new HomeAddressQuery("a2") .where.address().like("address") .end(); IQuery query = leftQuery .join(rightQuery) .on(l -> l.where.homeAddressId(), r -> r.where.id()).endJoin() .build(); List entities = this.mapper.listEntity(query); ``` -------------------------------- ### Gradle 插件应用 (Groovy) Source: https://mybatis-flex.com/zh/others/kapt.html 在 Gradle 项目中应用 kotlin-kapt 插件(Groovy 语法)。 ```groovy plugins { id 'org.jetbrains.kotlin.kapt' version '1.9.20' } ``` -------------------------------- ### MyBatis-Plus Pagination Query Source: https://mybatis-flex.com/zh/intro/benchmark.html Example of how to perform a paginated query using MyBatis-Plus. ```java LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.ge(PlusAccount::getId, 100); queryWrapper.eq(PlusAccount::getEmail, "michael@gmail.com"); Page p = Page.of(page, pageSize, 20000, false); mapper.selectPage(p, queryWrapper); ``` -------------------------------- ### 示例配置 Source: https://mybatis-flex.com/zh/others/apt.html 展示了如何使用包名表达式 `${entityPackage}`、`${entityPackage.parent}`、`${entityPackage.parent.parent}` 来配置包名。 ```properties processor.allInTables.package=${entityPackage}.table processor.mapper.package=${entityPackage.parent}.mapper processor.tableDef.package=${entityPackage.parent.parent}.table ``` -------------------------------- ### MyBatis-Flex Pagination Query Source: https://mybatis-flex.com/zh/intro/benchmark.html Example of how to perform a paginated query using MyBatis-Flex. ```java QueryWrapper queryWrapper = new QueryWrapper() .where(FLEX_ACCOUNT.ID.ge(100)); mapper.paginate(page, pageSize, 20000, queryWrapper); ``` -------------------------------- ### Partial Field Update (Fluent-MyBatis) Source: https://mybatis-flex.com/zh/intro/comparison.html Example of updating specific fields using Fluent-MyBatis. ```java AccountUpdate update = new AccountUpdate() .update.userName().is("michael") .age().is(18) .birthday().is(null) .end() .where.id().eq(100) .end(); accountMapper.updateBy(update); ``` -------------------------------- ### Gradle 依赖添加 (Kotlin) Source: https://mybatis-flex.com/zh/others/kapt.html 在 Gradle 项目的 dependencies 块中添加 mybatis-flex-processor 依赖,并使用 kapt 配置。 ```kotlin dependencies { kapt("com.mybatis-flex:mybatis-flex-processor:1.5.6") } ``` -------------------------------- ### Multi-Table Query 2 (MyBatis-Flex) Source: https://mybatis-flex.com/zh/intro/comparison.html Example of a multi-table query with aliases using MyBatis-Flex. ```java QueryWrapper query = new QueryWrapper() .select( ACCOUNT.ID , ACCOUNT.USER_NAME , ARTICLE.ID.as("articleId") , ARTICLE.TITLE) .from(ACCOUNT.as("a"), ARTICLE.as("b")) .where(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID)); ``` -------------------------------- ### Enable MyBatis-Flex-Admin Logging Source: https://mybatis-flex.com/zh/base/configuration.html Configuration to enable and set up the connection to MyBatis-Flex-Admin for SQL auditing. Ensure the secret-key matches the one configured in the MyBatis-Flex-Admin project. ```yaml mybatis-flex: admin-config: enable: true endpoint: http://admin-host:8080/message/collect secret-key: secretKey ``` -------------------------------- ### Multi-Table Query 1 (MyBatis-Flex) Source: https://mybatis-flex.com/zh/intro/comparison.html Example of a left join query using MyBatis-Flex. ```java QueryWrapper query = QueryWrapper.create() .select().from(ACCOUNT) .leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID)) .where(ACCOUNT.AGE.ge(10)); List accounts = mapper.selectListByQuery(query); ``` -------------------------------- ### Paginated Query with Db + Row in Java Source: https://mybatis-flex.com/zh/base/db-row.html Illustrates how to perform paginated queries using QueryWrapper and the Db tool, specifying table, page number, page size, and query conditions. ```java QueryWrapper query=QueryWrapper.create() .where(ACCOUNT.AGE.ge(18)); Page rowPage=Db.paginate("tb_account",3,10,query); ```