From ea714cf1117389abd59c1d6fac1055027a32b7bf Mon Sep 17 00:00:00 2001 From: hubin Date: Mon, 14 Oct 2024 22:17:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=20solon=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E6=A8=A1=E5=9D=97=E7=BB=93=E6=9E=84=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .kotlin/errors/errors-1726886507129.log | 4 + changelog-temp.md | 5 + gradle.properties | 2 +- .../mybatisplus/test/mapper/BMapper.java | 1 - mybatis-plus-extension/build.gradle | 3 - .../{Model.java => AbstractModel.java} | 16 +- .../mybatisplus/extension/ddl/DdlHelper.java | 10 +- .../repository/AbstractRepository.java | 128 ++++++++ .../IRepository.java} | 140 +------- .../extension/service/impl/ServiceImpl.java | 310 ------------------ .../extension/toolkit/SqlHelper.java | 54 +-- .../generator/config/po/TableInfo.java | 3 +- mybatis-plus-solon-plugin/build.gradle | 17 + .../override/SolonMybatisMapperProxy.java | 33 ++ .../extension/activerecord/Model.java | 39 +++ .../compatible/SolonCompatibleSet.java | 80 +++++ .../mybatisplus/extension/ddl/SimpleDdl.java | 45 +++ .../extension/repository/CrudRepository.java | 103 ++++++ .../extension/service/IService.java | 72 ++++ .../extension/service/impl/ServiceImpl.java | 30 ++ .../extension/service/impl/package-info.java | 0 .../extension/service/package-info.java | 0 .../extension/toolkit/SqlRunner.java | 244 ++++++++++++++ .../MybatisAdapterFactoryPlus.java | 24 ++ .../solon/integration/MybatisAdapterPlus.java | 146 +++++++++ .../solon/integration/SolonSqlSession.java | 209 ++++++++++++ .../solon/integration/XPluginImpl.java | 39 +++ .../MybatisPlusRuntimeNativeRegistrar.java | 68 ++++ .../mybatis-plus-solon-plugin.properties | 2 + .../src/test/java/demo/Config.java | 50 +++ .../src/test/java/demo/DemoApp.java | 22 ++ .../java/demo/controller/IndexController.java | 21 ++ .../java/demo/dso/MetaObjectHandlerImpl.java | 19 ++ .../MybatisSqlSessionFactoryBuilderImpl.java | 9 + .../test/java/demo/dso/mapper/UserMapper.java | 10 + .../java/demo/dso/service/UserService.java | 24 ++ .../src/test/java/demo/model/User.java | 31 ++ .../IGenericTypeResolverImplTest.java | 27 ++ .../src/test/resources/app.yml | 25 ++ mybatis-plus-spring/build.gradle | 29 ++ .../extension/activerecord/Model.java | 39 +++ .../compatible/SpringCompatibleSet.java | 91 +++++ .../mybatisplus/extension/ddl/SimpleDdl.java | 0 .../extension/repository/CrudRepository.java | 103 ++++++ .../extension/service/IService.java | 75 +++++ .../extension/service/impl/ServiceImpl.java | 30 ++ .../extension/service/impl/package-info.java | 22 ++ .../extension/service}/package-info.java | 7 +- .../spring/MybatisSqlSessionFactoryBean.java | 14 +- .../extension/toolkit/SqlRunner.java | 0 .../mybatisplus/test/service/ServiceTest.java | 1 - .../test/logicdel/EntityMapper.java | 1 + .../mybatisplus/test/phoenix/PhoenixTest.java | 1 - .../test/sqlrunner/SqlRunnerTest.java | 2 - .../test/toolkit/SqlHelperTest.java | 9 +- settings.gradle | 2 + .../build.gradle | 2 + .../MybatisPlusAutoConfiguration.java | 5 + 58 files changed, 1962 insertions(+), 536 deletions(-) create mode 100644 .kotlin/errors/errors-1726886507129.log rename mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/{Model.java => AbstractModel.java} (94%) create mode 100644 mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/AbstractRepository.java rename mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/{service/IService.java => repository/IRepository.java} (79%) delete mode 100644 mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java create mode 100644 mybatis-plus-solon-plugin/build.gradle create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/core/override/SolonMybatisMapperProxy.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/compatible/SolonCompatibleSet.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java rename {mybatis-plus-extension => mybatis-plus-solon-plugin}/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java (100%) rename {mybatis-plus-extension => mybatis-plus-solon-plugin}/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java (100%) create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterFactoryPlus.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterPlus.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/SolonSqlSession.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/XPluginImpl.java create mode 100644 mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/aot/MybatisPlusRuntimeNativeRegistrar.java create mode 100644 mybatis-plus-solon-plugin/src/main/resources/META-INF/solon/mybatis-plus-solon-plugin.properties create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/Config.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/DemoApp.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/controller/IndexController.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/dso/MetaObjectHandlerImpl.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/dso/MybatisSqlSessionFactoryBuilderImpl.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/dso/mapper/UserMapper.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/dso/service/UserService.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/demo/model/User.java create mode 100644 mybatis-plus-solon-plugin/src/test/java/features/IGenericTypeResolverImplTest.java create mode 100644 mybatis-plus-solon-plugin/src/test/resources/app.yml create mode 100644 mybatis-plus-spring/build.gradle create mode 100644 mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java create mode 100644 mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/compatible/SpringCompatibleSet.java rename {mybatis-plus-extension => mybatis-plus-spring}/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java (100%) create mode 100644 mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java create mode 100644 mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java create mode 100644 mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java create mode 100644 mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java rename {mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring => mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service}/package-info.java (84%) rename {mybatis-plus-extension => mybatis-plus-spring}/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java (98%) rename {mybatis-plus-extension => mybatis-plus-spring}/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java (100%) rename {mybatis-plus-extension => mybatis-plus-spring}/src/test/java/com/baomidou/mybatisplus/test/service/ServiceTest.java (99%) diff --git a/.kotlin/errors/errors-1726886507129.log b/.kotlin/errors/errors-1726886507129.log new file mode 100644 index 000000000..7cd151b6c --- /dev/null +++ b/.kotlin/errors/errors-1726886507129.log @@ -0,0 +1,4 @@ +kotlin version: 2.0.20 +error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output: + 1. Kotlin compile daemon is ready + diff --git a/changelog-temp.md b/changelog-temp.md index e69de29bb..f6adafb3e 100644 --- a/changelog-temp.md +++ b/changelog-temp.md @@ -0,0 +1,5 @@ + +- opt: 优化代码生成器支持可视化配置生产能力 +- opt: 解构扩展包不再强制依赖 spring 开发框架 +- feat: 重构 service 模块抽象为 CrudRepository 不再建议使用 IService 避免业务层数据混乱 +- feat: 新增 solon 启动插件支持 diff --git a/gradle.properties b/gradle.properties index 6a5e09ef1..1ede209ea 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -APP_VERSION=3.5.8 +APP_VERSION=3.5.9 APP_GROUP=com.baomidou signing.keyId=1FD337F9 signing.password=243194995 diff --git a/mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/mapper/BMapper.java b/mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/mapper/BMapper.java index 5efcb73e4..69e4c000b 100644 --- a/mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/mapper/BMapper.java +++ b/mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/mapper/BMapper.java @@ -1,7 +1,6 @@ package com.baomidou.mybatisplus.test.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.test.entity.AEntity; import com.baomidou.mybatisplus.test.entity.BEntity; public interface BMapper extends BaseMapper { diff --git a/mybatis-plus-extension/build.gradle b/mybatis-plus-extension/build.gradle index 81a82a3c5..af120fb50 100644 --- a/mybatis-plus-extension/build.gradle +++ b/mybatis-plus-extension/build.gradle @@ -6,12 +6,9 @@ compileKotlin{ dependencies { api project(":mybatis-plus-core") - implementation "${lib."mybatis-spring"}" implementation "${lib."kotlin-stdlib-jdk8"}" implementation "${lib."kotlin-reflect"}" - implementation "${lib."spring-context-support"}" - implementation "${lib."spring-jdbc"}" implementation "${lib."slf4j-api"}" implementation "${lib."p6spy"}" implementation "${lib."jackson"}" diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/AbstractModel.java similarity index 94% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java rename to mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/AbstractModel.java index 4f9b6b3cc..4766bed43 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/AbstractModel.java @@ -21,11 +21,10 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.*; +import com.baomidou.mybatisplus.extension.compatible.CompatibleHelper; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; -import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.session.SqlSession; -import org.mybatis.spring.SqlSessionUtils; import java.io.Serializable; import java.util.List; @@ -43,11 +42,11 @@ import java.util.Objects; * @author hubin * @since 2016-11-06 */ -public abstract class Model> implements Serializable { +public abstract class AbstractModel> implements Serializable { private static final long serialVersionUID = 1L; - private final transient Class entityClass = this.getClass(); + protected final transient Class entityClass = this.getClass(); /** * 插入(字段选择插入) @@ -237,13 +236,6 @@ public abstract class Model> implements Serializable { } } - /** - * 执行 SQL - */ - public SqlRunner sql() { - return new SqlRunner(this.entityClass); - } - /** * 获取Session 默认自动提交 */ @@ -284,6 +276,6 @@ public abstract class Model> implements Serializable { * @param sqlSession session */ protected void closeSqlSession(SqlSession sqlSession) { - SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(this.entityClass)); + CompatibleHelper.getCompatibleSet().closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(this.entityClass)); } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/DdlHelper.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/DdlHelper.java index ece01d1bf..849041489 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/DdlHelper.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/DdlHelper.java @@ -17,17 +17,13 @@ package com.baomidou.mybatisplus.extension.ddl; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.toolkit.StringPool; -import com.baomidou.mybatisplus.extension.ddl.history.IDdlGenerator; -import com.baomidou.mybatisplus.extension.ddl.history.MysqlDdlGenerator; -import com.baomidou.mybatisplus.extension.ddl.history.OracleDdlGenerator; -import com.baomidou.mybatisplus.extension.ddl.history.PostgreDdlGenerator; -import com.baomidou.mybatisplus.extension.ddl.history.SQLiteDdlGenerator; +import com.baomidou.mybatisplus.extension.compatible.CompatibleHelper; +import com.baomidou.mybatisplus.extension.ddl.history.*; import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; import org.apache.ibatis.jdbc.SqlRunner; -import org.springframework.core.io.ClassPathResource; import javax.sql.DataSource; import java.io.*; @@ -126,7 +122,7 @@ public class DdlHelper { } public static InputStream getInputStream(String path) throws Exception { - return new ClassPathResource(path).getInputStream(); + return CompatibleHelper.getCompatibleSet().getInputStream(path); } protected static String getNowTime() { diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/AbstractRepository.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/AbstractRepository.java new file mode 100644 index 000000000..621e5ba00 --- /dev/null +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/AbstractRepository.java @@ -0,0 +1,128 @@ +package com.baomidou.mybatisplus.extension.repository; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.override.MybatisMapperProxy; +import com.baomidou.mybatisplus.core.toolkit.MybatisUtils; +import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.logging.LogFactory; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; + +public abstract class AbstractRepository, T> implements IRepository { + + protected final Log log = LogFactory.getLog(getClass()); + + /** + * @see #getEntityClass() + */ + private Class entityClass; + + @Override + public Class getEntityClass() { + if(this.entityClass == null) { + this.entityClass = (Class) GenericTypeUtils.resolveTypeArguments(this.getMapperClass(), BaseMapper.class)[0]; + } + return this.entityClass; + } + + /** + * @see #getMapperClass() + */ + private Class mapperClass; + + private volatile SqlSessionFactory sqlSessionFactory; + + protected SqlSessionFactory getSqlSessionFactory() { + if (this.sqlSessionFactory == null) { + MybatisMapperProxy mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this.getBaseMapper()); + this.sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy); + } + return this.sqlSessionFactory; + } + + /** + * @return baseMapper 真实类型 + * @since 3.5.7 + */ + public Class getMapperClass() { + if (this.mapperClass == null) { + MybatisMapperProxy mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this.getBaseMapper()); + this.mapperClass = (Class) mybatisMapperProxy.getMapperInterface(); + } + return this.mapperClass; + } + + /** + * TableId 注解存在更新记录,否插入一条记录 + * + * @param entity 实体对象 + * @return boolean + */ + @Override + public boolean saveOrUpdate(T entity) { + return getBaseMapper().insertOrUpdate(entity); + } + + @Override + public T getOne(Wrapper queryWrapper, boolean throwEx) { + return getBaseMapper().selectOne(queryWrapper, throwEx); + } + + @Override + public Optional getOneOpt(Wrapper queryWrapper, boolean throwEx) { + return Optional.ofNullable(getBaseMapper().selectOne(queryWrapper, throwEx)); + } + + @Override + public Map getMap(Wrapper queryWrapper) { + return SqlHelper.getObject(log, getBaseMapper().selectMaps(queryWrapper)); + } + + @Override + public V getObj(Wrapper queryWrapper, Function mapper) { + return SqlHelper.getObject(log, listObjs(queryWrapper, mapper)); + } + + /** + * 执行批量操作 + * + * @param list 数据集合 + * @param batchSize 批量大小 + * @param consumer 执行方法 + * @param 泛型 + * @return 操作结果 + * @since 3.3.1 + */ + protected boolean executeBatch(Collection list, int batchSize, BiConsumer consumer) { + return SqlHelper.executeBatch(getSqlSessionFactory(), this.log, list, batchSize, consumer); + } + + /** + * 执行批量操作(默认批次提交数量{@link IRepository#DEFAULT_BATCH_SIZE}) + * + * @param list 数据集合 + * @param consumer 执行方法 + * @param 泛型 + * @return 操作结果 + * @since 3.3.1 + */ + protected boolean executeBatch(Collection list, BiConsumer consumer) { + return executeBatch(list, DEFAULT_BATCH_SIZE, consumer); + } + + @Override + public boolean removeById(Serializable id, boolean useFill) { + return SqlHelper.retBool(getBaseMapper().deleteById(id, useFill)); + } + +} diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/IRepository.java similarity index 79% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java rename to mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/IRepository.java index 3f3b7fd3a..dbd4d8436 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/IRepository.java @@ -1,19 +1,4 @@ -/* - * Copyright (c) 2011-2024, baomidou (jobob@qq.com). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.baomidou.mybatisplus.extension.service; +package com.baomidou.mybatisplus.extension.repository; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; @@ -22,30 +7,21 @@ import com.baomidou.mybatisplus.core.toolkit.Assert; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.baomidou.mybatisplus.extension.conditions.query.ChainQuery; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper; -import com.baomidou.mybatisplus.extension.conditions.update.ChainUpdate; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper; import com.baomidou.mybatisplus.extension.kotlin.KtQueryChainWrapper; import com.baomidou.mybatisplus.extension.kotlin.KtUpdateChainWrapper; import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; -import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; -/** - * 顶级 Service - * - * @author hubin - * @since 2018-06-23 - */ -public interface IService { +public interface IRepository { /** * 默认批次提交数量 @@ -61,16 +37,6 @@ public interface IService { return SqlHelper.retBool(getBaseMapper().insert(entity)); } - /** - * 插入(批量) - * - * @param entityList 实体对象集合 - */ - @Transactional(rollbackFor = Exception.class) - default boolean saveBatch(Collection entityList) { - return saveBatch(entityList, DEFAULT_BATCH_SIZE); - } - /** * 插入(批量) * @@ -79,16 +45,6 @@ public interface IService { */ boolean saveBatch(Collection entityList, int batchSize); - /** - * 批量修改插入 - * - * @param entityList 实体对象集合 - */ - @Transactional(rollbackFor = Exception.class) - default boolean saveOrUpdateBatch(Collection entityList) { - return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE); - } - /** * 批量修改插入 * @@ -174,59 +130,6 @@ public interface IService { return SqlHelper.retBool(getBaseMapper().deleteByIds(list, useFill)); } - /** - * 批量删除(jdbc批量提交) - * - * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致) - * @return 删除结果 - * @since 3.5.0 - */ - @Transactional(rollbackFor = Exception.class) - default boolean removeBatchByIds(Collection list) { - return removeBatchByIds(list, DEFAULT_BATCH_SIZE); - } - - /** - * 批量删除(jdbc批量提交) - * - * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致) - * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除) - * @return 删除结果 - * @since 3.5.0 - */ - default boolean removeBatchByIds(Collection list, boolean useFill) { - return removeBatchByIds(list, DEFAULT_BATCH_SIZE, useFill); - } - - /** - * 批量删除(jdbc批量提交) - * - * @param list 主键ID或实体列表 - * @param batchSize 批次大小 - * @return 删除结果 - * @since 3.5.0 - * @deprecated 3.5.7 {@link #removeBatchByIds(Collection)} - */ - @Deprecated - default boolean removeBatchByIds(Collection list, int batchSize) { - throw new UnsupportedOperationException("不支持的方法!"); - } - - /** - * 批量删除(jdbc批量提交) - * - * @param list 主键ID或实体列表 - * @param batchSize 批次大小 - * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除) - * @return 删除结果 - * @since 3.5.0 - * @deprecated 3.5.7 {@link #removeBatchByIds(Collection)} - */ - @Deprecated - default boolean removeBatchByIds(Collection list, int batchSize, boolean useFill) { - throw new UnsupportedOperationException("不支持的方法!"); - } - /** * 根据 ID 选择修改 * @@ -256,16 +159,6 @@ public interface IService { return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper)); } - /** - * 根据ID 批量更新 - * - * @param entityList 实体对象集合 - */ - @Transactional(rollbackFor = Exception.class) - default boolean updateBatchById(Collection entityList) { - return updateBatchById(entityList, DEFAULT_BATCH_SIZE); - } - /** * 根据ID 批量更新 * @@ -570,20 +463,24 @@ public interface IService { */ Class getEntityClass(); - /** + /* * 以下的方法使用介绍: - * + *

* 一. 名称介绍 * 1. 方法名带有 query 的为对数据的查询操作, 方法名带有 update 的为对数据的修改操作 * 2. 方法名带有 lambda 的为内部方法入参 column 支持函数式的 + *

+ *

* 二. 支持介绍 - * * 1. 方法名带有 query 的支持以 {@link ChainQuery} 内部的方法名结尾进行数据查询操作 * 2. 方法名带有 update 的支持以 {@link ChainUpdate} 内部的方法名为结尾进行数据修改操作 + *

* + *

* 三. 使用示例,只用不带 lambda 的方法各展示一个例子,其他类推 * 1. 根据条件获取一条数据: `query().eq("column", value).one()` * 2. 根据条件删除一条数据: `update().eq("column", value).remove()` + *

* */ @@ -655,23 +552,4 @@ public interface IService { default LambdaUpdateChainWrapper lambdaUpdate() { return ChainWrappers.lambdaUpdateChain(getBaseMapper()); } - - /** - *

- * 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法 - * 此次修改主要是减少了此项业务代码的代码量(存在性验证之后的saveOrUpdate操作) - *

- *

- * 该方法不推荐在多线程并发下使用,并发可能存在间隙锁的问题,可以采用先查询后判断是否更新或保存。 - *

- *

- * 该方法存在安全隐患将在后续大版本删除 - *

- * - * @param entity 实体对象 - */ - @Deprecated - default boolean saveOrUpdate(T entity, Wrapper updateWrapper) { - return update(entity, updateWrapper) || saveOrUpdate(entity); - } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java deleted file mode 100644 index 347fa2651..000000000 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 2011-2024, baomidou (jobob@qq.com). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.baomidou.mybatisplus.extension.service.impl; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.enums.SqlMethod; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.TableInfo; -import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; -import com.baomidou.mybatisplus.core.override.MybatisMapperProxy; -import com.baomidou.mybatisplus.core.toolkit.*; -import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils; -import com.baomidou.mybatisplus.extension.service.IService; -import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; -import org.apache.ibatis.binding.MapperMethod; -import org.apache.ibatis.logging.Log; -import org.apache.ibatis.logging.LogFactory; -import org.apache.ibatis.session.ExecutorType; -import org.apache.ibatis.session.SqlSession; -import org.apache.ibatis.session.SqlSessionFactory; -import org.mybatis.spring.SqlSessionUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Map; -import java.util.Optional; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * IService 实现类( 泛型:M 是 mapper 对象,T 是实体 ) - * - * @author hubin - * @since 2018-06-23 - */ -@SuppressWarnings("unchecked") -public abstract class ServiceImpl, T> implements IService { - - protected final Log log = LogFactory.getLog(getClass()); - - @Autowired - protected M baseMapper; - - @Override - public M getBaseMapper() { - Assert.notNull(this.baseMapper, "baseMapper can not be null"); - return this.baseMapper; - } - - /** - * @see #getEntityClass() - */ - private Class entityClass; - - @Override - public Class getEntityClass() { - if(this.entityClass == null) { - this.entityClass = (Class) GenericTypeUtils.resolveTypeArguments(this.getMapperClass(), BaseMapper.class)[0]; - } - return this.entityClass; - } - - /** - * @see #currentMapperClass() - */ - private Class mapperClass; - - private volatile SqlSessionFactory sqlSessionFactory; - - protected SqlSessionFactory getSqlSessionFactory() { - if (this.sqlSessionFactory == null) { - MybatisMapperProxy mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this.getBaseMapper()); - this.sqlSessionFactory = MybatisUtils.getSqlSessionFactory(mybatisMapperProxy); - } - return this.sqlSessionFactory; - } - - /** - * 判断数据库操作是否成功 - * - * @param result 数据库操作返回影响条数 - * @return boolean - * @deprecated 3.3.1 - */ - @Deprecated - protected boolean retBool(Integer result) { - return SqlHelper.retBool(result); - } - - /** - * @return baseMapper 真实类型 - * @deprecated 3.5.7 {@link #getMapperClass()} - */ - @Deprecated - protected Class currentMapperClass() { - return this.getMapperClass(); - } - - /** - * @return baseMapper 真实类型 - * @since 3.5.7 - */ - public Class getMapperClass() { - if (this.mapperClass == null) { - MybatisMapperProxy mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this.getBaseMapper()); - this.mapperClass = (Class) mybatisMapperProxy.getMapperInterface(); - } - return this.mapperClass; - } - - /** - * @return 实体类型 - * @deprecated 3.5.7 {@link #getEntityClass()} - */ - @Deprecated - protected Class currentModelClass() { - return getEntityClass(); - } - - - /** - * 批量操作 SqlSession - * - * @deprecated 3.3.0 - */ - @Deprecated - protected SqlSession sqlSessionBatch() { - return getSqlSessionFactory().openSession(ExecutorType.BATCH); - } - - /** - * 释放sqlSession - * - * @param sqlSession session - * @deprecated 3.3.0 - */ - @Deprecated - protected void closeSqlSession(SqlSession sqlSession) { - SqlSessionUtils.closeSqlSession(sqlSession, getSqlSessionFactory()); - } - - /** - * 获取 SqlStatement - * - * @param sqlMethod ignore - * @return ignore - * @see #getSqlStatement(SqlMethod) - * @deprecated 3.4.0 - */ - @Deprecated - protected String sqlStatement(SqlMethod sqlMethod) { - return SqlHelper.table(getEntityClass()).getSqlStatement(sqlMethod.getMethod()); - } - - /** - * 批量插入 - * - * @param entityList ignore - * @param batchSize ignore - * @return ignore - */ - @Transactional(rollbackFor = Exception.class) - @Override - public boolean saveBatch(Collection entityList, int batchSize) { - String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE); - return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity)); - } - - /** - * 获取mapperStatementId - * - * @param sqlMethod 方法名 - * @return 命名id - * @since 3.4.0 - */ - protected String getSqlStatement(SqlMethod sqlMethod) { - return SqlHelper.getSqlStatement(this.currentMapperClass(), sqlMethod); - } - - /** - * TableId 注解存在更新记录,否插入一条记录 - * - * @param entity 实体对象 - * @return boolean - */ - @Override - public boolean saveOrUpdate(T entity) { - return getBaseMapper().insertOrUpdate(entity); - } - - @Transactional(rollbackFor = Exception.class) - @Override - public boolean saveOrUpdateBatch(Collection entityList, int batchSize) { - TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass()); - Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); - String keyProperty = tableInfo.getKeyProperty(); - Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); - return SqlHelper.saveOrUpdateBatch(getSqlSessionFactory(), this.currentMapperClass(), this.log, entityList, batchSize, (sqlSession, entity) -> { - Object idVal = tableInfo.getPropertyValue(entity, keyProperty); - return StringUtils.checkValNull(idVal) - || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity)); - }, (sqlSession, entity) -> { - MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); - param.put(Constants.ENTITY, entity); - sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param); - }); - } - - @Transactional(rollbackFor = Exception.class) - @Override - public boolean updateBatchById(Collection entityList, int batchSize) { - String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID); - return executeBatch(entityList, batchSize, (sqlSession, entity) -> { - MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); - param.put(Constants.ENTITY, entity); - sqlSession.update(sqlStatement, param); - }); - } - - @Override - public T getOne(Wrapper queryWrapper, boolean throwEx) { - return getBaseMapper().selectOne(queryWrapper, throwEx); - } - - @Override - public Optional getOneOpt(Wrapper queryWrapper, boolean throwEx) { - return Optional.ofNullable(getBaseMapper().selectOne(queryWrapper, throwEx)); - } - - @Override - public Map getMap(Wrapper queryWrapper) { - return SqlHelper.getObject(log, getBaseMapper().selectMaps(queryWrapper)); - } - - @Override - public V getObj(Wrapper queryWrapper, Function mapper) { - return SqlHelper.getObject(log, listObjs(queryWrapper, mapper)); - } - - /** - * 执行批量操作 - * - * @param consumer consumer - * @since 3.3.0 - * @deprecated 3.3.1 后面我打算移除掉 {@link #executeBatch(Collection, int, BiConsumer)} }. - */ - @Deprecated - protected boolean executeBatch(Consumer consumer) { - return SqlHelper.executeBatch(getSqlSessionFactory(), this.log, consumer); - } - - /** - * 执行批量操作 - * - * @param list 数据集合 - * @param batchSize 批量大小 - * @param consumer 执行方法 - * @param 泛型 - * @return 操作结果 - * @since 3.3.1 - */ - protected boolean executeBatch(Collection list, int batchSize, BiConsumer consumer) { - return SqlHelper.executeBatch(getSqlSessionFactory(), this.log, list, batchSize, consumer); - } - - /** - * 执行批量操作(默认批次提交数量{@link IService#DEFAULT_BATCH_SIZE}) - * - * @param list 数据集合 - * @param consumer 执行方法 - * @param 泛型 - * @return 操作结果 - * @since 3.3.1 - */ - protected boolean executeBatch(Collection list, BiConsumer consumer) { - return executeBatch(list, DEFAULT_BATCH_SIZE, consumer); - } - - @Override - public boolean removeById(Serializable id, boolean useFill) { - return SqlHelper.retBool(getBaseMapper().deleteById(id, useFill)); - } - - @Override - public boolean removeBatchByIds(Collection list, int batchSize) { - return SqlHelper.retBool(getBaseMapper().deleteByIds(list)); - } - - @Override - public boolean removeBatchByIds(Collection list, int batchSize, boolean useFill) { - return SqlHelper.retBool(getBaseMapper().deleteByIds(list, useFill)); - } - -} diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlHelper.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlHelper.java index 5046912bb..45de2419f 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlHelper.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlHelper.java @@ -21,18 +21,12 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import com.baomidou.mybatisplus.core.toolkit.*; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; -import lombok.SneakyThrows; -import org.apache.ibatis.exceptions.PersistenceException; +import com.baomidou.mybatisplus.extension.compatible.CompatibleHelper; import org.apache.ibatis.executor.BatchResult; import org.apache.ibatis.logging.Log; -import org.apache.ibatis.reflection.ExceptionUtil; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; -import org.mybatis.spring.MyBatisExceptionTranslator; -import org.mybatis.spring.SqlSessionHolder; -import org.mybatis.spring.SqlSessionUtils; -import org.springframework.transaction.support.TransactionSynchronizationManager; import java.sql.Statement; import java.util.Collection; @@ -92,7 +86,7 @@ public final class SqlHelper { */ @Deprecated public static SqlSession sqlSession(Class clazz) { - return SqlSessionUtils.getSqlSession(GlobalConfigUtils.currentSessionFactory(clazz)); + return CompatibleHelper.getCompatibleSet().getSqlSession(GlobalConfigUtils.currentSessionFactory(clazz)); } /** @@ -188,40 +182,8 @@ public final class SqlHelper { return executeBatch(sqlSessionFactory(entityClass), log, consumer); } - @SneakyThrows public static boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Consumer consumer) { - SqlSessionHolder sqlSessionHolder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sqlSessionFactory); - boolean transaction = TransactionSynchronizationManager.isSynchronizationActive(); - if (sqlSessionHolder != null) { - SqlSession sqlSession = sqlSessionHolder.getSqlSession(); - //原生无法支持执行器切换,当存在批量操作时,会嵌套两个session的,优先commit上一个session - //按道理来说,这里的值应该一直为false。 - sqlSession.commit(!transaction); - } - SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); - if (!transaction) { - log.warn("SqlSession [" + sqlSession + "] Transaction not enabled"); - } - try { - consumer.accept(sqlSession); - //非事务情况下,强制commit。 - sqlSession.commit(!transaction); - return true; - } catch (Throwable t) { - sqlSession.rollback(); - Throwable unwrapped = ExceptionUtil.unwrapThrowable(t); - if (unwrapped instanceof PersistenceException) { - MyBatisExceptionTranslator myBatisExceptionTranslator - = new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true); - Throwable throwable = myBatisExceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); - if (throwable != null) { - throw throwable; - } - } - throw ExceptionUtils.mpe(unwrapped); - } finally { - sqlSession.close(); - } + return CompatibleHelper.getCompatibleSet().executeBatch(sqlSessionFactory, log, consumer); } /** @@ -318,9 +280,9 @@ public final class SqlHelper { * 例: {@code * SqlSession sqlSession = SqlHelper.sqlSession(entityClass); * try { - * BaseMapper userMapper = getMapper(User.class, sqlSession); + * BaseMapper userMapper = getMapper(User.class, sqlSession); * } finally { - * sqlSession.close(); + * sqlSession.close(); * } * } * @@ -330,7 +292,7 @@ public final class SqlHelper { * @return Mapper */ @SuppressWarnings("unchecked") - public static > M getMapper(Class entityClass, SqlSession sqlSession) { + public static > M getMapper(Class entityClass, SqlSession sqlSession) { Assert.notNull(entityClass, "entityClass can't be null!"); TableInfo tableInfo = Optional.ofNullable(TableInfoHelper.getTableInfo(entityClass)).orElseThrow(() -> ExceptionUtils.mpe("Can not find TableInfo from Class: \"%s\".", entityClass.getName())); Class mapperClass = ClassUtils.toClassConfident(tableInfo.getCurrentNamespace()); @@ -347,12 +309,12 @@ public final class SqlHelper { * @param Mapper类型 * @return 返回lambda执行结果 */ - public static > R execute(Class entityClass, SFunction sFunction) { + public static > R execute(Class entityClass, SFunction sFunction) { SqlSession sqlSession = SqlHelper.sqlSession(entityClass); try { return sFunction.apply(SqlHelper.getMapper(entityClass, sqlSession)); } finally { - SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(entityClass)); + CompatibleHelper.getCompatibleSet().closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(entityClass)); } } } diff --git a/mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java b/mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java index f5a17ba4d..6978677c4 100644 --- a/mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java +++ b/mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java @@ -17,7 +17,6 @@ package com.baomidou.mybatisplus.generator.config.po; import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.core.toolkit.StringUtils; -import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder; @@ -229,7 +228,7 @@ public class TableInfo { } else { if (entity.isActiveRecord()) { // 无父类开启 AR 模式 - this.importPackages.add(Model.class.getCanonicalName()); + this.importPackages.add("com.baomidou.mybatisplus.extension.activerecord.Model"); } } if (entity.isSerialVersionUID() || entity.isActiveRecord()) { diff --git a/mybatis-plus-solon-plugin/build.gradle b/mybatis-plus-solon-plugin/build.gradle new file mode 100644 index 000000000..cb8b5e3aa --- /dev/null +++ b/mybatis-plus-solon-plugin/build.gradle @@ -0,0 +1,17 @@ +apply plugin: 'kotlin' + +compileKotlin{ + kotlinOptions.jvmTarget = "1.8" +} + +dependencies { + api project(":mybatis-plus-extension") + api "org.noear:mybatis-solon-plugin:3.0.0" + api "org.noear:solon-aot:3.0.0" + testImplementation "org.noear:solon-test:3.0.0" + testImplementation "io.github.classgraph:classgraph:4.8.176" + testImplementation "com.zaxxer:HikariCP:4.0.3" + testImplementation "${lib.h2}" + testImplementation "${lib.mysql}" + testImplementation "${lib.'logback-classic'}" +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/core/override/SolonMybatisMapperProxy.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/core/override/SolonMybatisMapperProxy.java new file mode 100644 index 000000000..a635ab02b --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/core/override/SolonMybatisMapperProxy.java @@ -0,0 +1,33 @@ +package com.baomidou.mybatisplus.core.override; + +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; + +import java.lang.reflect.Method; + +public class SolonMybatisMapperProxy extends MybatisMapperProxy { + + private final SqlSessionFactory factory; + private final Class mapperInterface; + private final SqlSession sqlSession; + + public SolonMybatisMapperProxy(SqlSessionFactory sqlSessionFactory, SqlSession sqlSession, Class mapperInterface) { + super(null, mapperInterface, null); + this.factory = sqlSessionFactory; + this.sqlSession = sqlSession; + this.mapperInterface = mapperInterface; + } + + @Override + public SqlSession getSqlSession() { + return sqlSession; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + try (SqlSession session = factory.openSession(true)) { + Object mapper = session.getMapper(mapperInterface); + return method.invoke(mapper, args); + } + } +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java new file mode 100644 index 000000000..667cab8f8 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.activerecord; + +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; + +/** + * ActiveRecord 模式 CRUD + *

+ * 必须存在对应的原始mapper并继承baseMapper并且可以使用的前提下 + * 才能使用此 AR 模式 !!! + *

+ * + * @param + * @author hubin + * @since 2016-11-06 + */ +public abstract class Model> extends AbstractModel { + + /** + * 执行 SQL + */ + public SqlRunner sql() { + return new SqlRunner(this.entityClass); + } +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/compatible/SolonCompatibleSet.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/compatible/SolonCompatibleSet.java new file mode 100644 index 000000000..1e4fb7d52 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/compatible/SolonCompatibleSet.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.compatible; + +import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.reflection.ExceptionUtil; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.noear.solon.core.util.GenericUtil; +import org.noear.solon.core.util.ResourceUtil; +import org.noear.solon.data.tran.TranUtils; + +import java.io.InputStream; +import java.util.function.Consumer; + +/** + * spring 兼容方法集接口实现类 + */ +public class SolonCompatibleSet implements CompatibleSet { + + @Override + public SqlSession getSqlSession(SqlSessionFactory sessionFactory) { + return sessionFactory.openSession(); + } + + @Override + public void closeSqlSession(SqlSession sqlSession, SqlSessionFactory sqlSessionFactory) { + if (sqlSession != null) { + sqlSession.close(); + } + } + + @Override + public boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Consumer consumer) { + boolean transaction = TranUtils.inTrans(); + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + if (!transaction) { + log.warn("SqlSession [" + sqlSession + "] Transaction not enabled"); + } + try { + consumer.accept(sqlSession); + //非事务情况下,强制commit。 + sqlSession.commit(!transaction); + return true; + } catch (RuntimeException t) { + throw t; + } catch (Throwable t) { + sqlSession.rollback(); + Throwable unwrapped = ExceptionUtil.unwrapThrowable(t); + if (unwrapped instanceof RuntimeException) { + throw (RuntimeException) unwrapped; + } else { + throw ExceptionUtils.mpe(unwrapped); + } + } finally { + sqlSession.close(); + } + } + + @Override + public InputStream getInputStream(String path) throws Exception { + return ResourceUtil.findResource(path).openStream(); + } + +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java new file mode 100644 index 000000000..52ea76279 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.ddl; + +import org.noear.solon.annotation.Inject; + +import javax.sql.DataSource; +import java.util.List; +import java.util.function.Consumer; + +/** + * 非多数据源 DDL 实现 + * + * @author hubin + * @since 2021-09-23 + */ +public class SimpleDdl implements IDdl { + + @Inject + private DataSource dataSource; + + @Override + public void runScript(Consumer consumer) { + consumer.accept(dataSource); + } + + @Override + public List getSqlFiles() { + return null; + } + +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java new file mode 100644 index 000000000..7e4e46b28 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.repository; + +import com.baomidou.mybatisplus.core.enums.SqlMethod; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import org.apache.ibatis.binding.MapperMethod; +import org.noear.solon.annotation.Inject; +import org.noear.solon.data.annotation.Tran; + +import java.util.Collection; + +/** + * IService 实现类( 泛型:M 是 mapper 对象,T 是实体 ) + * + * @author hubin + * @since 2018-06-23 + */ +public abstract class CrudRepository, T> extends AbstractRepository { + + @Inject + protected M baseMapper; + + @Override + public M getBaseMapper() { + Assert.notNull(this.baseMapper, "baseMapper can not be null"); + return this.baseMapper; + } + + /** + * 批量插入 + * + * @param entityList ignore + * @param batchSize ignore + * @return ignore + */ + @Tran + @Override + public boolean saveBatch(Collection entityList, int batchSize) { + String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE); + return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity)); + } + + /** + * 获取mapperStatementId + * + * @param sqlMethod 方法名 + * @return 命名id + * @since 3.4.0 + */ + protected String getSqlStatement(SqlMethod sqlMethod) { + return SqlHelper.getSqlStatement(this.getMapperClass(), sqlMethod); + } + + @Tran + @Override + public boolean saveOrUpdateBatch(Collection entityList, int batchSize) { + TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass()); + Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); + String keyProperty = tableInfo.getKeyProperty(); + Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); + return SqlHelper.saveOrUpdateBatch(getSqlSessionFactory(), this.getMapperClass(), this.log, entityList, batchSize, (sqlSession, entity) -> { + Object idVal = tableInfo.getPropertyValue(entity, keyProperty); + return StringUtils.checkValNull(idVal) + || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity)); + }, (sqlSession, entity) -> { + MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); + param.put(Constants.ENTITY, entity); + sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param); + }); + } + + @Tran + @Override + public boolean updateBatchById(Collection entityList, int batchSize) { + String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID); + return executeBatch(entityList, batchSize, (sqlSession, entity) -> { + MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); + param.put(Constants.ENTITY, entity); + sqlSession.update(sqlStatement, param); + }); + } +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java new file mode 100644 index 000000000..352a5b892 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.service; + +import com.baomidou.mybatisplus.extension.repository.IRepository; +import org.noear.solon.data.annotation.Tran; + +import java.util.Collection; + +/** + * 顶级 Service + * + * @author hubin + * @since 2018-06-23 + */ +public interface IService extends IRepository { + + /** + * 插入(批量) + * + * @param entityList 实体对象集合 + */ + @Tran + default boolean saveBatch(Collection entityList) { + return saveBatch(entityList, DEFAULT_BATCH_SIZE); + } + + /** + * 批量修改插入 + * + * @param entityList 实体对象集合 + */ + @Tran + default boolean saveOrUpdateBatch(Collection entityList) { + return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE); + } + + /** + * 批量删除(jdbc批量提交) + * + * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致) + * @return 删除结果 + * @since 3.5.0 + */ + @Tran + default boolean removeBatchByIds(Collection list) { + return removeByIds(list); + } + + /** + * 根据ID 批量更新 + * + * @param entityList 实体对象集合 + */ + @Tran + default boolean updateBatchById(Collection entityList) { + return updateBatchById(entityList, DEFAULT_BATCH_SIZE); + } +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java new file mode 100644 index 000000000..6b3333964 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.service.impl; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.repository.CrudRepository; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * IService 实现类( 泛型:M 是 mapper 对象,T 是实体 ) + * + * @author hubin + * @since 2018-06-23 + */ +public class ServiceImpl, T> extends CrudRepository implements IService { + +} diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java similarity index 100% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java rename to mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java similarity index 100% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java rename to mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java new file mode 100644 index 000000000..45f1ab23e --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.toolkit; + +import com.baomidou.mybatisplus.core.assist.ISqlRunner; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.logging.LogFactory; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.noear.solon.data.annotation.Tran; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * SqlRunner 执行 SQL + * + * @author Caratacus + * @since 2016-12-11 + */ +public class SqlRunner implements ISqlRunner { + + // 单例Query + public static final SqlRunner DEFAULT = new SqlRunner(); + private final Log log = LogFactory.getLog(SqlRunner.class); + private Class clazz; + + public SqlRunner() { + } + + public SqlRunner(Class clazz) { + this.clazz = clazz; + } + + /** + * 获取默认的SqlQuery(适用于单库) + * + * @return ignore + */ + public static SqlRunner db() { + return DEFAULT; + } + + /** + * 根据当前class对象获取SqlQuery(适用于多库) + * + * @param clazz ignore + * @return ignore + */ + public static SqlRunner db(Class clazz) { + return new SqlRunner(clazz); + } + + @Tran + @Override + public boolean insert(String sql, Object... args) { + SqlSession sqlSession = sqlSession(); + try { + return SqlHelper.retBool(sqlSession.insert(INSERT, sqlMap(sql, args))); + } finally { + closeSqlSession(sqlSession); + } + } + + @Tran + @Override + public boolean delete(String sql, Object... args) { + SqlSession sqlSession = sqlSession(); + try { + return SqlHelper.retBool(sqlSession.delete(DELETE, sqlMap(sql, args))); + } finally { + closeSqlSession(sqlSession); + } + } + + /** + * 获取sqlMap参数 + * + * @param sql 指定参数的格式: {0}, {1} + * @param args 仅支持String + * @return ignore + */ + private Map sqlMap(String sql, Object... args) { + Map sqlMap = CollectionUtils.newHashMapWithExpectedSize(1); + sqlMap.put(SQL, StringUtils.sqlArgsFill(sql, args)); + return sqlMap; + } + + /** + * 获取sqlMap参数 + * + * @param sql 指定参数的格式: {0}, {1} + * @param page 分页模型 + * @param args 仅支持String + * @return ignore + */ + private Map sqlMap(String sql, IPage page, Object... args) { + Map sqlMap = CollectionUtils.newHashMapWithExpectedSize(2); + sqlMap.put(PAGE, page); + sqlMap.put(SQL, StringUtils.sqlArgsFill(sql, args)); + return sqlMap; + } + + @Tran + @Override + public boolean update(String sql, Object... args) { + SqlSession sqlSession = sqlSession(); + try { + return SqlHelper.retBool(sqlSession.update(UPDATE, sqlMap(sql, args))); + } finally { + closeSqlSession(sqlSession); + } + } + + /** + * 根据sql查询Map结果集 + *

SqlRunner.db().selectList("select * from tbl_user where name={0}", "Caratacus")

+ * + * @param sql sql语句,可添加参数,格式:{0},{1} + * @param args 只接受String格式 + * @return ignore + */ + @Override + public List> selectList(String sql, Object... args) { + SqlSession sqlSession = sqlSession(); + try { + return sqlSession.selectList(SELECT_LIST, sqlMap(sql, args)); + } finally { + closeSqlSession(sqlSession); + } + } + + /** + * 根据sql查询一个字段值的结果集 + *

注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@code selectList()}

+ * + * @param sql sql语句,可添加参数,格式:{0},{1} + * @param args 只接受String格式 + * @return ignore + */ + @Override + public List selectObjs(String sql, Object... args) { + SqlSession sqlSession = sqlSession(); + try { + return sqlSession.selectList(SELECT_OBJS, sqlMap(sql, args)); + } finally { + closeSqlSession(sqlSession); + } + } + + /** + * 根据sql查询一个字段值的一条结果 + *

注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@code selectOne()}

+ * + * @param sql sql语句,可添加参数,格式:{0},{1} + * @param args 只接受String格式 + * @return ignore + */ + @Override + public Object selectObj(String sql, Object... args) { + return SqlHelper.getObject(log, selectObjs(sql, args)); + } + + @Override + public long selectCount(String sql, Object... args) { + SqlSession sqlSession = sqlSession(); + try { + return SqlHelper.retCount(sqlSession.selectOne(COUNT, sqlMap(sql, args))); + } finally { + closeSqlSession(sqlSession); + } + } + + @Override + public Map selectOne(String sql, Object... args) { + return SqlHelper.getObject(log, selectList(sql, args)); + } + + @Override + public >> E selectPage(E page, String sql, Object... args) { + if (null == page) { + return null; + } + SqlSession sqlSession = sqlSession(); + try { + page.setRecords(sqlSession.selectList(SELECT_LIST, sqlMap(sql, page, args))); + } finally { + closeSqlSession(sqlSession); + } + return page; + } + + /** + * 获取Session 默认自动提交 + */ + private SqlSession sqlSession() { + return getSqlSessionFactory().openSession(); + } + + /** + * 释放sqlSession + * + * @param sqlSession session + */ + private void closeSqlSession(SqlSession sqlSession) { + if (sqlSession != null) { + sqlSession.close(); + } + } + + /** + * 获取SqlSessionFactory + */ + private SqlSessionFactory getSqlSessionFactory() { + return Optional.ofNullable(clazz).map(GlobalConfigUtils::currentSessionFactory).orElse(SqlHelper.FACTORY); + } + + /** + * @deprecated 3.5.3.2 + */ + @Deprecated + public void close() { + + } + +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterFactoryPlus.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterFactoryPlus.java new file mode 100644 index 000000000..9bdd251bd --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterFactoryPlus.java @@ -0,0 +1,24 @@ +package com.baomidou.mybatisplus.solon.integration; + +import org.apache.ibatis.solon.MybatisAdapter; +import org.apache.ibatis.solon.MybatisAdapterFactory; +import org.noear.solon.core.BeanWrap; +import org.noear.solon.core.Props; + +/** + * 适配器工厂 for mybatis-plus + * + * @author noear, iYarnFog + * @since 1.5 + */ +public class MybatisAdapterFactoryPlus implements MybatisAdapterFactory { + @Override + public MybatisAdapter create(BeanWrap dsWrap) { + return new MybatisAdapterPlus(dsWrap); + } + + @Override + public MybatisAdapter create(BeanWrap dsWrap, Props dsProps) { + return new MybatisAdapterPlus(dsWrap, dsProps); + } +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterPlus.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterPlus.java new file mode 100644 index 000000000..7bf9bde8f --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/MybatisAdapterPlus.java @@ -0,0 +1,146 @@ +package com.baomidou.mybatisplus.solon.integration; + +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; +import com.baomidou.mybatisplus.core.config.GlobalConfig; +import com.baomidou.mybatisplus.core.override.SolonMybatisMapperProxy; +import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.solon.integration.MybatisAdapterDefault; +import org.noear.solon.Utils; +import org.noear.solon.core.BeanWrap; +import org.noear.solon.core.Props; +import org.noear.solon.core.VarHolder; + +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; + +/** + * 适配器 for mybatis-plus + *

+ * 1.提供 mapperScan 能力 + * 2.生成 factory 的能力 + * + * @author noear, iYarnFog + * @since 1.5 + */ +public class MybatisAdapterPlus extends MybatisAdapterDefault { + + MybatisSqlSessionFactoryBuilder factoryBuilderPlus; + GlobalConfig globalConfig; + SqlSession sqlSession; + Map, Object> mapperCached = new HashMap<>(); + + /** + * 构建Sql工厂适配器,使用默认的 typeAliases 和 mappers 配置 + */ + protected MybatisAdapterPlus(BeanWrap dsWrap) { + super(dsWrap); + + this.factoryBuilderPlus = new MybatisSqlSessionFactoryBuilder(); + + dsWrap.context().getBeanAsync(MybatisSqlSessionFactoryBuilder.class, bean -> { + factoryBuilderPlus = bean; + }); + } + + /** + * 构建Sql工厂适配器,使用属性配置 + */ + protected MybatisAdapterPlus(BeanWrap dsWrap, Props dsProps) { + super(dsWrap, dsProps); + + this.factoryBuilderPlus = new MybatisSqlSessionFactoryBuilder(); + + dsWrap.context().getBeanAsync(MybatisSqlSessionFactoryBuilder.class, bean -> { + factoryBuilderPlus = bean; + }); + } + + /** + * 初始化配置 + */ + @Override + protected void initConfiguration(Environment environment) { + //for configuration section + config = new MybatisConfiguration(environment); + + Props cfgProps = dsProps.getProp("configuration"); + if (cfgProps.size() > 0) { + Utils.injectProperties(config, cfgProps); + } + + + //for globalConfig section + globalConfig = new GlobalConfig().setDbConfig(new GlobalConfig.DbConfig()); + + Props globalProps = dsProps.getProp("globalConfig"); + if (globalProps.size() > 0) { + //尝试配置注入 + Utils.injectProperties(globalConfig, globalProps); + } + + GlobalConfigUtils.setGlobalConfig(config, globalConfig); + } + + /** + * 获取会话工厂 + */ + @Override + public SqlSessionFactory getFactory() { + if (factory == null) { + factory = factoryBuilderPlus.build(getConfiguration()); + } + + return factory; + } + + public SqlSession getSession() { + if (sqlSession == null) { + sqlSession = new SolonSqlSession(getFactory()); + } + return sqlSession; + } + + @Override + public T getMapper(Class mapperClz) { + Object mapper = mapperCached.get(mapperClz); + + if (mapper == null) { + synchronized (mapperClz) { + mapper = mapperCached.get(mapperClz); + if (mapper == null) { + SolonMybatisMapperProxy tMybatisMapperProxy = new SolonMybatisMapperProxy<>(getFactory(), getSession(), mapperClz); + mapper = Proxy.newProxyInstance( + mapperClz.getClassLoader(), + new Class[]{mapperClz}, + tMybatisMapperProxy); + mapperCached.put(mapperClz, mapper); + } + } + } + + return (T) mapper; + } + + /** + * 获取全局配置 + */ + public GlobalConfig getGlobalConfig() { + return globalConfig; + } + + @Override + public void injectTo(VarHolder varH) { + super.injectTo(varH); + + //@Db("db1") SqlSessionFactory factory; + if (GlobalConfig.class.isAssignableFrom(varH.getType())) { + varH.setValue(this.getGlobalConfig()); + return; + } + } +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/SolonSqlSession.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/SolonSqlSession.java new file mode 100644 index 000000000..451d0d917 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/SolonSqlSession.java @@ -0,0 +1,209 @@ +package com.baomidou.mybatisplus.solon.integration; + +import org.apache.ibatis.cursor.Cursor; +import org.apache.ibatis.executor.BatchResult; +import org.apache.ibatis.reflection.ExceptionUtil; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.noear.solon.data.tran.TranUtils; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Connection; +import java.util.List; +import java.util.Map; + +public class SolonSqlSession implements SqlSession { + + private final SqlSessionFactory sqlSessionFactory; + private final SqlSession sqlSessionProxy; + + public SolonSqlSession(SqlSessionFactory sqlSessionFactory) { + this.sqlSessionFactory = sqlSessionFactory; + this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionInterceptor()); + } + + public SqlSessionFactory getSqlSessionFactory() { + return this.sqlSessionFactory; + } + + public SqlSession getSqlSessionProxy() { + return this.sqlSessionProxy; + } + + @Override + public T selectOne(String statement) { + return this.sqlSessionProxy.selectOne(statement); + } + + @Override + public T selectOne(String statement, Object parameter) { + return this.sqlSessionProxy.selectOne(statement, parameter); + } + + @Override + public Map selectMap(String statement, String mapKey) { + return this.sqlSessionProxy.selectMap(statement, mapKey); + } + + @Override + public Map selectMap(String statement, Object parameter, String mapKey) { + return this.sqlSessionProxy.selectMap(statement, parameter, mapKey); + } + + @Override + public Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) { + return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds); + } + + @Override + public Cursor selectCursor(String statement) { + return this.sqlSessionProxy.selectCursor(statement); + } + + @Override + public Cursor selectCursor(String statement, Object parameter) { + return this.sqlSessionProxy.selectCursor(statement, parameter); + } + + @Override + public Cursor selectCursor(String statement, Object parameter, RowBounds rowBounds) { + return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds); + } + + @Override + public List selectList(String statement) { + return this.sqlSessionProxy.selectList(statement); + } + + @Override + public List selectList(String statement, Object parameter) { + return this.sqlSessionProxy.selectList(statement, parameter); + } + + @Override + public List selectList(String statement, Object parameter, RowBounds rowBounds) { + return this.sqlSessionProxy.selectList(statement, parameter, rowBounds); + } + + @Override + public void select(String statement, ResultHandler handler) { + this.sqlSessionProxy.select(statement, handler); + } + + @Override + public void select(String statement, Object parameter, ResultHandler handler) { + this.sqlSessionProxy.select(statement, parameter, handler); + } + + @Override + public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { + this.sqlSessionProxy.select(statement, parameter, rowBounds, handler); + } + + @Override + public int insert(String statement) { + return this.sqlSessionProxy.insert(statement); + } + + @Override + public int insert(String statement, Object parameter) { + return this.sqlSessionProxy.insert(statement, parameter); + } + + @Override + public int update(String statement) { + return this.sqlSessionProxy.update(statement); + } + + @Override + public int update(String statement, Object parameter) { + return this.sqlSessionProxy.update(statement, parameter); + } + + @Override + public int delete(String statement) { + return this.sqlSessionProxy.delete(statement); + } + + @Override + public int delete(String statement, Object parameter) { + return this.sqlSessionProxy.delete(statement, parameter); + } + + @Override + public T getMapper(Class type) { + return this.getConfiguration().getMapper(type, this); + } + + @Override + public void commit() { + throw new UnsupportedOperationException("Manual commit is not allowed over a Solon managed SqlSession"); + } + + @Override + public void commit(boolean force) { + throw new UnsupportedOperationException("Manual commit is not allowed over a Solon managed SqlSession"); + } + + @Override + public void rollback() { + throw new UnsupportedOperationException("Manual rollback is not allowed over a Solon managed SqlSession"); + } + + @Override + public void rollback(boolean force) { + throw new UnsupportedOperationException("Manual rollback is not allowed over a Solon managed SqlSession"); + } + + @Override + public void close() { + throw new UnsupportedOperationException("Manual close is not allowed over a Solon managed SqlSession"); + } + + @Override + public void clearCache() { + this.sqlSessionProxy.clearCache(); + } + + @Override + public Configuration getConfiguration() { + return this.sqlSessionFactory.getConfiguration(); + } + + @Override + public Connection getConnection() { + return this.sqlSessionProxy.getConnection(); + } + + @Override + public List flushStatements() { + return this.sqlSessionProxy.flushStatements(); + } + + private class SqlSessionInterceptor implements InvocationHandler { + private SqlSessionInterceptor() { + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Object unwrapped; + try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) { + Object result = method.invoke(sqlSession, args); + sqlSession.commit(!TranUtils.inTrans()); + unwrapped = result; + } catch (Throwable var11) { + unwrapped = ExceptionUtil.unwrapThrowable(var11); + if (unwrapped instanceof RuntimeException) { + throw (RuntimeException) unwrapped; + } + throw (Throwable) unwrapped; + } + return unwrapped; + } + } +} \ No newline at end of file diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/XPluginImpl.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/XPluginImpl.java new file mode 100644 index 000000000..4ea409e80 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/XPluginImpl.java @@ -0,0 +1,39 @@ +package com.baomidou.mybatisplus.solon.integration; + +import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils; +import com.baomidou.mybatisplus.extension.compatible.CompatibleHelper; +import com.baomidou.mybatisplus.extension.compatible.SolonCompatibleSet; +import com.baomidou.mybatisplus.solon.integration.aot.MybatisPlusRuntimeNativeRegistrar; +import org.noear.solon.aot.RuntimeNativeRegistrar; +import org.noear.solon.core.AppContext; +import org.noear.solon.core.runtime.NativeDetector; +import org.noear.solon.core.util.ClassUtil; +import org.noear.solon.core.util.GenericUtil; +import org.apache.ibatis.solon.integration.MybatisAdapterManager; +import org.noear.solon.core.Plugin; + +/** + * @author noear + * @since 1.5 + */ +public class XPluginImpl implements Plugin { + + @Override + public void start(AppContext context) { + // + // 此插件的 solon.plugin.priority 会大于 mybatis-solon-plugin 的值 + // + MybatisAdapterManager.setAdapterFactory(new MybatisAdapterFactoryPlus()); + + // 注入兼容配置 + CompatibleHelper.setCompatibleSet(new SolonCompatibleSet()); + + // 提供反射处理类 + GenericTypeUtils.setGenericTypeResolver((GenericUtil::resolveTypeArguments)); + + // aot + if (NativeDetector.isAotRuntime() && ClassUtil.hasClass(() -> RuntimeNativeRegistrar.class)) { + context.wrapAndPut(MybatisPlusRuntimeNativeRegistrar.class); + } + } +} diff --git a/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/aot/MybatisPlusRuntimeNativeRegistrar.java b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/aot/MybatisPlusRuntimeNativeRegistrar.java new file mode 100644 index 000000000..c1b040e08 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/java/com/baomidou/mybatisplus/solon/integration/aot/MybatisPlusRuntimeNativeRegistrar.java @@ -0,0 +1,68 @@ +package com.baomidou.mybatisplus.solon.integration.aot; + +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver; +import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper; +import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; +import com.baomidou.mybatisplus.core.conditions.ISqlSegment; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.interfaces.Compare; +import com.baomidou.mybatisplus.core.conditions.interfaces.Func; +import com.baomidou.mybatisplus.core.conditions.interfaces.Join; +import com.baomidou.mybatisplus.core.conditions.interfaces.Nested; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.Query; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import org.noear.solon.aot.RuntimeNativeMetadata; +import org.noear.solon.aot.RuntimeNativeRegistrar; +import org.noear.solon.aot.hint.ExecutableMode; +import org.noear.solon.aot.hint.MemberCategory; +import org.noear.solon.core.AppContext; + +import java.lang.invoke.SerializedLambda; + +/** + * mybatis-plus aot 注册 native 元数据 + * + * @author songyinyin + * @since 2.3 + */ +public class MybatisPlusRuntimeNativeRegistrar implements RuntimeNativeRegistrar { + + @Override + public void register(AppContext context, RuntimeNativeMetadata metadata) { + metadata.registerDefaultConstructor(MybatisXMLLanguageDriver.class); + metadata.registerReflection(MybatisConfiguration.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + metadata.registerAllDeclaredMethod(MybatisConfiguration.class, ExecutableMode.INVOKE); + + metadata.registerReflection(AbstractLambdaWrapper.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + + metadata.registerJdkProxy(AbstractWrapper.DoSomething.class); + metadata.registerReflection(AbstractWrapper.DoSomething.class); + metadata.registerReflection(AbstractWrapper.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + metadata.registerAllDeclaredMethod(AbstractWrapper.class, ExecutableMode.INVOKE); + + metadata.registerReflection(ISqlSegment.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + metadata.registerReflection(Wrapper.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + + metadata.registerAllDeclaredMethod(Wrapper.class, ExecutableMode.INVOKE); + + metadata.registerReflection(Compare.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + metadata.registerReflection(Func.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + metadata.registerReflection(Join.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + metadata.registerReflection(Nested.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + + metadata.registerReflection(LambdaQueryWrapper.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_METHODS, + MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS); + metadata.registerAllDeclaredMethod(LambdaQueryWrapper.class, ExecutableMode.INVOKE); + + metadata.registerReflection(Query.class, MemberCategory.DECLARED_FIELDS, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS); + + metadata.registerAllDeclaredMethod(BaseMapper.class, ExecutableMode.INVOKE); + + metadata.registerSerialization(SerializedLambda.class); + metadata.registerSerialization(SFunction.class); + } + +} diff --git a/mybatis-plus-solon-plugin/src/main/resources/META-INF/solon/mybatis-plus-solon-plugin.properties b/mybatis-plus-solon-plugin/src/main/resources/META-INF/solon/mybatis-plus-solon-plugin.properties new file mode 100644 index 000000000..660b0bb3e --- /dev/null +++ b/mybatis-plus-solon-plugin/src/main/resources/META-INF/solon/mybatis-plus-solon-plugin.properties @@ -0,0 +1,2 @@ +solon.plugin=com.baomidou.mybatisplus.solon.integration.XPluginImpl +solon.plugin.priority=30 \ No newline at end of file diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/Config.java b/mybatis-plus-solon-plugin/src/test/java/demo/Config.java new file mode 100644 index 000000000..e7b915360 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/Config.java @@ -0,0 +1,50 @@ +package demo; + +import com.baomidou.mybatisplus.core.MybatisConfiguration; +import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; +import com.baomidou.mybatisplus.core.config.GlobalConfig; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.zaxxer.hikari.HikariDataSource; +import demo.dso.MetaObjectHandlerImpl; +import demo.dso.MybatisSqlSessionFactoryBuilderImpl; +import okhttp3.Interceptor; +import org.apache.ibatis.solon.annotation.Db; +import org.noear.solon.Solon; +import org.noear.solon.annotation.Bean; +import org.noear.solon.annotation.Configuration; +import org.noear.solon.annotation.Inject; + +import javax.sql.DataSource; + +@Configuration +public class Config { + @Bean("db1") + public DataSource db1(@Inject("${dataSource.db1}") HikariDataSource hikariDataSource) { + return hikariDataSource; + } + +// @Bean +// public Interceptor plusInterceptor() { +// MybatisPlusInterceptor plusInterceptor = new MybatisPlusInterceptor(); +// plusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); +// return plusInterceptor; +// } + + @Bean + public void db1_ext(@Db("db1") GlobalConfig globalConfig) { + MetaObjectHandler metaObjectHandler = new MetaObjectHandlerImpl(); + + globalConfig.setMetaObjectHandler(metaObjectHandler); + } + + @Bean + public void db1_ext2(@Db("db1") MybatisConfiguration config){ + config.getTypeHandlerRegistry().register("xxx"); + config.setDefaultEnumTypeHandler(null); + } + + @Bean + public MybatisSqlSessionFactoryBuilder factoryBuilderNew(){ + return new MybatisSqlSessionFactoryBuilderImpl(); + } +} diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/DemoApp.java b/mybatis-plus-solon-plugin/src/test/java/demo/DemoApp.java new file mode 100644 index 000000000..3ce885e1f --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/DemoApp.java @@ -0,0 +1,22 @@ +package demo; + +import com.baomidou.mybatisplus.core.toolkit.Assert; +import demo.dso.service.UserService; +import demo.model.User; +import org.noear.solon.Solon; + +import java.util.List; + +/** + * @author noear 2021/7/12 created + */ +public class DemoApp { + public static void main(String[] args) { + Solon.start(DemoApp.class, args); + + //test + UserService userService = Solon.context().getBean(UserService.class); + + Assert.notNull(userService.getUserList(), "查询结果异常"); + } +} diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/controller/IndexController.java b/mybatis-plus-solon-plugin/src/test/java/demo/controller/IndexController.java new file mode 100644 index 000000000..d33137183 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/controller/IndexController.java @@ -0,0 +1,21 @@ +package demo.controller; + +import demo.dso.service.UserService; +import demo.model.User; +import org.noear.solon.annotation.Controller; +import org.noear.solon.annotation.Inject; +import org.noear.solon.annotation.Mapping; + +import java.util.List; + +@Controller +public class IndexController { + + @Inject + UserService userService; + + @Mapping("/") + public List index() { + return userService.getUserList(); + } +} diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/dso/MetaObjectHandlerImpl.java b/mybatis-plus-solon-plugin/src/test/java/demo/dso/MetaObjectHandlerImpl.java new file mode 100644 index 000000000..3e7bc842f --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/dso/MetaObjectHandlerImpl.java @@ -0,0 +1,19 @@ +package demo.dso; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; + +/** + * @author noear 2022/4/17 created + */ +public class MetaObjectHandlerImpl implements MetaObjectHandler { + @Override + public void insertFill(MetaObject metaObject) { + + } + + @Override + public void updateFill(MetaObject metaObject) { + + } +} diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/dso/MybatisSqlSessionFactoryBuilderImpl.java b/mybatis-plus-solon-plugin/src/test/java/demo/dso/MybatisSqlSessionFactoryBuilderImpl.java new file mode 100644 index 000000000..184fc9a7d --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/dso/MybatisSqlSessionFactoryBuilderImpl.java @@ -0,0 +1,9 @@ +package demo.dso; + +import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; + +/** + * @author noear 2021/10/20 created + */ +public class MybatisSqlSessionFactoryBuilderImpl extends MybatisSqlSessionFactoryBuilder { +} diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/dso/mapper/UserMapper.java b/mybatis-plus-solon-plugin/src/test/java/demo/dso/mapper/UserMapper.java new file mode 100644 index 000000000..8986e2a94 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/dso/mapper/UserMapper.java @@ -0,0 +1,10 @@ +package demo.dso.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import demo.model.User; + +/** + * @author 颖 + */ +public interface UserMapper extends BaseMapper { +} \ No newline at end of file diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/dso/service/UserService.java b/mybatis-plus-solon-plugin/src/test/java/demo/dso/service/UserService.java new file mode 100644 index 000000000..5724e23a9 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/dso/service/UserService.java @@ -0,0 +1,24 @@ +package demo.dso.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import demo.dso.mapper.UserMapper; +import demo.model.User; +import org.noear.solon.annotation.Component; +import org.noear.solon.annotation.Inject; + +import java.util.List; + +/** + * @author noear 2021/9/9 created + */ +@Component +public class UserService { + @Inject + UserMapper userMapper; + + public List getUserList() { + assert userMapper != null; + + return userMapper.selectList(new QueryWrapper<>()); + } +} diff --git a/mybatis-plus-solon-plugin/src/test/java/demo/model/User.java b/mybatis-plus-solon-plugin/src/test/java/demo/model/User.java new file mode 100644 index 000000000..faff025da --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/demo/model/User.java @@ -0,0 +1,31 @@ +package demo.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +/** + * @author iYarnFog + */ +@TableName(value = "users") +public class User { + @TableId(type = IdType.AUTO) + private Long id; + private String uuid; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/mybatis-plus-solon-plugin/src/test/java/features/IGenericTypeResolverImplTest.java b/mybatis-plus-solon-plugin/src/test/java/features/IGenericTypeResolverImplTest.java new file mode 100644 index 000000000..a2307e904 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/java/features/IGenericTypeResolverImplTest.java @@ -0,0 +1,27 @@ +package features; + + +import com.baomidou.mybatisplus.core.mapper.Mapper; +import demo.dso.mapper.UserMapper; +import org.junit.jupiter.api.Test; +import org.noear.solon.core.util.GenericUtil; + +import java.util.Arrays; +import java.util.Map; + +public class IGenericTypeResolverImplTest { + + + @Test + public void resolveTypeArguments() { + System.out.println(Arrays.toString(GenericUtil.resolveTypeArguments(DemoImpl.class, Map.class))); + System.out.println(Arrays.toString(GenericUtil.resolveTypeArguments(DemoImpl.class, Demo.class))); + + System.out.println(Arrays.toString(GenericUtil.resolveTypeArguments(UserMapper.class, Mapper.class))); + } + + private interface Demo {} + private abstract static class DemoImpl implements Map, IGenericTypeResolverImplTest.Demo { + + } +} \ No newline at end of file diff --git a/mybatis-plus-solon-plugin/src/test/resources/app.yml b/mybatis-plus-solon-plugin/src/test/resources/app.yml new file mode 100644 index 000000000..bd9926b35 --- /dev/null +++ b/mybatis-plus-solon-plugin/src/test/resources/app.yml @@ -0,0 +1,25 @@ +server: + port: 6040 + +# 配置数据源 +dataSource: + db1: + # 与数据库名可用保持一致 + schema: test + jdbcUrl: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true + driverClassName: com.mysql.cj.jdbc.Driver + username: root + password: 1234 + +mybatis: + db1: + mappers: + - "demo.dso.mapper.*" + configuration: + cacheEnabled: false + mapUnderscoreToCamelCase: true + globalConfig: + banner: false + metaObjectHandler: "demo.dso.MetaObjectHandlerImpl" + dbConfig: + logicDeleteField: "deleted" diff --git a/mybatis-plus-spring/build.gradle b/mybatis-plus-spring/build.gradle new file mode 100644 index 000000000..dca81a546 --- /dev/null +++ b/mybatis-plus-spring/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'kotlin' + +compileKotlin{ + kotlinOptions.jvmTarget = "1.8" +} + +dependencies { + api project(":mybatis-plus-extension") + implementation "${lib."mybatis-spring"}" + + implementation "${lib."kotlin-stdlib-jdk8"}" + implementation "${lib."kotlin-reflect"}" + implementation "${lib."spring-context-support"}" + implementation "${lib."spring-jdbc"}" + implementation "${lib."slf4j-api"}" + implementation "${lib."p6spy"}" + implementation "${lib."jackson"}" + implementation "${lib."fastjson"}" + implementation "${lib."gson"}" + implementation "${lib['mybatis-thymeleaf']}" + implementation "${lib.'mybatis-velocity'}" + implementation "${lib.'mybatis-freemarker'}" + implementation "de.ruedigermoeller:fst:3.0.4-jdk17" + implementation "com.github.ben-manes.caffeine:caffeine:2.9.3" + testImplementation "io.github.classgraph:classgraph:4.8.176" + testImplementation "${lib.h2}" + testImplementation "${lib.mysql}" + testImplementation "${lib.'logback-classic'}" +} diff --git a/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java new file mode 100644 index 000000000..667cab8f8 --- /dev/null +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.activerecord; + +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; + +/** + * ActiveRecord 模式 CRUD + *

+ * 必须存在对应的原始mapper并继承baseMapper并且可以使用的前提下 + * 才能使用此 AR 模式 !!! + *

+ * + * @param + * @author hubin + * @since 2016-11-06 + */ +public abstract class Model> extends AbstractModel { + + /** + * 执行 SQL + */ + public SqlRunner sql() { + return new SqlRunner(this.entityClass); + } +} diff --git a/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/compatible/SpringCompatibleSet.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/compatible/SpringCompatibleSet.java new file mode 100644 index 000000000..aa3df1b5e --- /dev/null +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/compatible/SpringCompatibleSet.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.compatible; + +import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; +import lombok.SneakyThrows; +import org.apache.ibatis.exceptions.PersistenceException; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.reflection.ExceptionUtil; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.MyBatisExceptionTranslator; +import org.mybatis.spring.SqlSessionHolder; +import org.mybatis.spring.SqlSessionUtils; +import org.springframework.core.io.ClassPathResource; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import java.io.InputStream; +import java.util.function.Consumer; + +/** + * spring 兼容方法集接口实现类 + */ +public class SpringCompatibleSet implements CompatibleSet { + + @Override + public SqlSession getSqlSession(SqlSessionFactory sessionFactory) { + return SqlSessionUtils.getSqlSession(sessionFactory); + } + + @Override + public void closeSqlSession(SqlSession sqlSession, SqlSessionFactory sqlSessionFactory) { + SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory); + } + + @SneakyThrows + @Override + public boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Consumer consumer) { + SqlSessionHolder sqlSessionHolder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sqlSessionFactory); + boolean transaction = TransactionSynchronizationManager.isSynchronizationActive(); + if (sqlSessionHolder != null) { + SqlSession sqlSession = sqlSessionHolder.getSqlSession(); + //原生无法支持执行器切换,当存在批量操作时,会嵌套两个session的,优先commit上一个session + //按道理来说,这里的值应该一直为false。 + sqlSession.commit(!transaction); + } + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + if (!transaction) { + log.warn("SqlSession [" + sqlSession + "] Transaction not enabled"); + } + try { + consumer.accept(sqlSession); + //非事务情况下,强制commit。 + sqlSession.commit(!transaction); + return true; + } catch (Throwable t) { + sqlSession.rollback(); + Throwable unwrapped = ExceptionUtil.unwrapThrowable(t); + if (unwrapped instanceof PersistenceException) { + MyBatisExceptionTranslator myBatisExceptionTranslator + = new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true); + Throwable throwable = myBatisExceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); + if (throwable != null) { + throw throwable; + } + } + throw ExceptionUtils.mpe(unwrapped); + } finally { + sqlSession.close(); + } + } + + @Override + public InputStream getInputStream(String path) throws Exception { + return new ClassPathResource(path).getInputStream(); + } +} diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java similarity index 100% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java rename to mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/ddl/SimpleDdl.java diff --git a/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java new file mode 100644 index 000000000..805353772 --- /dev/null +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/repository/CrudRepository.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.repository; + +import com.baomidou.mybatisplus.core.enums.SqlMethod; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import org.apache.ibatis.binding.MapperMethod; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; + +/** + * IService 实现类( 泛型:M 是 mapper 对象,T 是实体 ) + * + * @author hubin + * @since 2018-06-23 + */ +public abstract class CrudRepository, T> extends AbstractRepository { + + @Autowired + protected M baseMapper; + + @Override + public M getBaseMapper() { + Assert.notNull(this.baseMapper, "baseMapper can not be null"); + return this.baseMapper; + } + + /** + * 批量插入 + * + * @param entityList ignore + * @param batchSize ignore + * @return ignore + */ + @Transactional(rollbackFor = Exception.class) + @Override + public boolean saveBatch(Collection entityList, int batchSize) { + String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE); + return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity)); + } + + /** + * 获取mapperStatementId + * + * @param sqlMethod 方法名 + * @return 命名id + * @since 3.4.0 + */ + protected String getSqlStatement(SqlMethod sqlMethod) { + return SqlHelper.getSqlStatement(this.getMapperClass(), sqlMethod); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean saveOrUpdateBatch(Collection entityList, int batchSize) { + TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass()); + Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!"); + String keyProperty = tableInfo.getKeyProperty(); + Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!"); + return SqlHelper.saveOrUpdateBatch(getSqlSessionFactory(), this.getMapperClass(), this.log, entityList, batchSize, (sqlSession, entity) -> { + Object idVal = tableInfo.getPropertyValue(entity, keyProperty); + return StringUtils.checkValNull(idVal) + || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity)); + }, (sqlSession, entity) -> { + MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); + param.put(Constants.ENTITY, entity); + sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param); + }); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean updateBatchById(Collection entityList, int batchSize) { + String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID); + return executeBatch(entityList, batchSize, (sqlSession, entity) -> { + MapperMethod.ParamMap param = new MapperMethod.ParamMap<>(); + param.put(Constants.ENTITY, entity); + sqlSession.update(sqlStatement, param); + }); + } +} diff --git a/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java new file mode 100644 index 000000000..2441f82fd --- /dev/null +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/IService.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.service; + +import com.baomidou.mybatisplus.extension.repository.IRepository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; + +/** + * 顶级 Service + *

+ * + *

+ * + * @author hubin + * @since 2018-06-23 + */ +public interface IService extends IRepository { + + /** + * 插入(批量) + * + * @param entityList 实体对象集合 + */ + @Transactional(rollbackFor = Exception.class) + default boolean saveBatch(Collection entityList) { + return saveBatch(entityList, DEFAULT_BATCH_SIZE); + } + + /** + * 批量修改插入 + * + * @param entityList 实体对象集合 + */ + @Transactional(rollbackFor = Exception.class) + default boolean saveOrUpdateBatch(Collection entityList) { + return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE); + } + + /** + * 批量删除(jdbc批量提交) + * + * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致) + * @return 删除结果 + * @since 3.5.0 + */ + @Transactional(rollbackFor = Exception.class) + default boolean removeBatchByIds(Collection list) { + return removeByIds(list); + } + + /** + * 根据ID 批量更新 + * + * @param entityList 实体对象集合 + */ + @Transactional(rollbackFor = Exception.class) + default boolean updateBatchById(Collection entityList) { + return updateBatchById(entityList, DEFAULT_BATCH_SIZE); + } +} diff --git a/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java new file mode 100644 index 000000000..6b3333964 --- /dev/null +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.baomidou.mybatisplus.extension.service.impl; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.repository.CrudRepository; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * IService 实现类( 泛型:M 是 mapper 对象,T 是实体 ) + * + * @author hubin + * @since 2018-06-23 + */ +public class ServiceImpl, T> extends CrudRepository implements IService { + +} diff --git a/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java new file mode 100644 index 000000000..8e6be58a8 --- /dev/null +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/impl/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2011-2024, baomidou (jobob@qq.com). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * 通用 service 实现 + * + * @author hubin + * @since 2018-06-08 + */ +package com.baomidou.mybatisplus.extension.service.impl; diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/package-info.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java similarity index 84% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/package-info.java rename to mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java index d8d67ca04..92566b86c 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/package-info.java +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/service/package-info.java @@ -14,6 +14,9 @@ * limitations under the License. */ /** - * Spring相关类 + * 通用 Service 接口 + * + * @author hubin + * @since 2018-06-08 */ -package com.baomidou.mybatisplus.extension.spring; +package com.baomidou.mybatisplus.extension.service; diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java similarity index 98% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java rename to mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java index d2fdc7a2e..fd1f992dd 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java +++ b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java @@ -15,11 +15,7 @@ */ package com.baomidou.mybatisplus.extension.spring; -import com.baomidou.mybatisplus.core.MybatisConfiguration; -import com.baomidou.mybatisplus.core.MybatisPlusVersion; -import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; -import com.baomidou.mybatisplus.core.MybatisXMLConfigBuilder; -import com.baomidou.mybatisplus.core.MybatisXMLMapperBuilder; +import com.baomidou.mybatisplus.core.*; import com.baomidou.mybatisplus.core.config.GlobalConfig; import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; @@ -61,13 +57,7 @@ import javax.sql.DataSource; import java.io.IOException; import java.lang.reflect.Modifier; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Properties; -import java.util.Set; +import java.util.*; import java.util.function.IntFunction; import java.util.stream.Stream; diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java b/mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java similarity index 100% rename from mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java rename to mybatis-plus-spring/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SqlRunner.java diff --git a/mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/test/service/ServiceTest.java b/mybatis-plus-spring/src/test/java/com/baomidou/mybatisplus/test/service/ServiceTest.java similarity index 99% rename from mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/test/service/ServiceTest.java rename to mybatis-plus-spring/src/test/java/com/baomidou/mybatisplus/test/service/ServiceTest.java index 582ac1cf7..3fab8d970 100644 --- a/mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/test/service/ServiceTest.java +++ b/mybatis-plus-spring/src/test/java/com/baomidou/mybatisplus/test/service/ServiceTest.java @@ -10,7 +10,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; - import static org.assertj.core.api.Assertions.assertThat; /** diff --git a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/logicdel/EntityMapper.java b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/logicdel/EntityMapper.java index e85a2c124..8b3a5217b 100644 --- a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/logicdel/EntityMapper.java +++ b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/logicdel/EntityMapper.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.toolkit.Constants; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; + import java.util.List; diff --git a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/PhoenixTest.java b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/PhoenixTest.java index ef8450b6d..b297c7992 100644 --- a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/PhoenixTest.java +++ b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/phoenix/PhoenixTest.java @@ -16,7 +16,6 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; - import static com.baomidou.mybatisplus.core.enums.SqlMethod.UPSERT_ONE; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/sqlrunner/SqlRunnerTest.java b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/sqlrunner/SqlRunnerTest.java index 9b9ef2420..a5f8077b4 100644 --- a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/sqlrunner/SqlRunnerTest.java +++ b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/sqlrunner/SqlRunnerTest.java @@ -13,8 +13,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import static org.assertj.core.api.Assertions.assertThat; - /** * @author miemie * @since 2021-03-16 diff --git a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/toolkit/SqlHelperTest.java b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/toolkit/SqlHelperTest.java index c8af871b0..294abc9b0 100644 --- a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/toolkit/SqlHelperTest.java +++ b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/toolkit/SqlHelperTest.java @@ -1,16 +1,15 @@ package com.baomidou.mybatisplus.test.toolkit; -import java.util.Arrays; -import java.util.List; - -import org.junit.jupiter.api.Test; - import com.baomidou.mybatisplus.core.toolkit.Assert; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; import com.baomidou.mybatisplus.test.BaseDbTest; import com.baomidou.mybatisplus.test.rewrite.Entity; import com.baomidou.mybatisplus.test.rewrite.EntityMapper; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; /** * SqlHelper 工具类测试 diff --git a/settings.gradle b/settings.gradle index 7b7793e6e..93217ae1a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,6 +21,8 @@ include 'mybatis-plus-annotation' include 'mybatis-plus-extension' include 'mybatis-plus-generator' include 'mybatis-plus-bom' +include 'mybatis-plus-spring' +include 'mybatis-plus-solon-plugin' include 'spring-boot-starter' include ':spring-boot-starter:mybatis-plus-boot-starter' include ':spring-boot-starter:mybatis-plus-boot-starter-test' diff --git a/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/build.gradle b/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/build.gradle index 6e1027bb3..a80cc5224 100644 --- a/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/build.gradle +++ b/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/build.gradle @@ -1,4 +1,6 @@ dependencies { + api project(":mybatis-plus-spring") + implementation project(":mybatis-plus") implementation "${lib."mybatis-spring"}" implementation "org.springframework.boot:spring-boot-autoconfigure:${springBootVersion}" diff --git a/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.java b/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.java index 89fa192e3..84c53e848 100644 --- a/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.java +++ b/spring-boot-starter/mybatis-plus-spring-boot-autoconfigure/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.java @@ -24,6 +24,8 @@ import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler; import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.core.injector.ISqlInjector; +import com.baomidou.mybatisplus.extension.compatible.CompatibleHelper; +import com.baomidou.mybatisplus.extension.compatible.SpringCompatibleSet; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.mapping.DatabaseIdProvider; @@ -148,6 +150,9 @@ public class MybatisPlusAutoConfiguration implements InitializingBean { this.sqlSessionFactoryBeanCustomizers = sqlSessionFactoryBeanCustomizers.getIfAvailable(); this.mybatisPlusPropertiesCustomizers = mybatisPlusPropertiesCustomizerProvider.getIfAvailable(); this.applicationContext = applicationContext; + + // 注入兼容配置 + CompatibleHelper.setCompatibleSet(new SpringCompatibleSet()); } @Override