diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java index 6581842b..25f4627b 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/BaseMapper.java @@ -55,12 +55,6 @@ public interface BaseMapper { */ int DEFAULT_BATCH_SIZE = 1000; - - default QueryWrapperChain queryChain() { - return new QueryWrapperChain<>(this); - } - - // === 增(insert) === /** diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/Mappers.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/Mappers.java index 8363465f..dda16903 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/Mappers.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/Mappers.java @@ -23,10 +23,14 @@ import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.util.MapUtil; +import java.lang.invoke.MethodHandles; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** @@ -77,6 +81,8 @@ public class Mappers { static class MapperHandler implements InvocationHandler { + private static final Set ignoreMethods = new HashSet<>(Arrays.asList("queryChain","updateChain")); + private static final MethodHandles.Lookup lookup = MethodHandles.lookup(); private Class mapperClass; private final SqlSessionFactory sqlSessionFactory = FlexGlobalConfig.getDefaultConfig().getSqlSessionFactory(); private final ExecutorType executorType = FlexGlobalConfig.getDefaultConfig().getConfiguration().getDefaultExecutorType(); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryWrapperChain.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryWrapperChain.java index d420c43b..b6838e9a 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryWrapperChain.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/QueryWrapperChain.java @@ -41,18 +41,6 @@ public class QueryWrapperChain extends QueryWrapperAdapter(baseMapper); } - public boolean remove() { - return SqlUtil.toBool(baseMapper.deleteByQuery(this)); - } - - public boolean update(T entity) { - return SqlUtil.toBool(baseMapper.updateByQuery(entity, this)); - } - - public boolean update(T entity, boolean ignoreNulls) { - return SqlUtil.toBool(baseMapper.updateByQuery(entity, ignoreNulls, this)); - } - public long count() { return baseMapper.selectCountByQuery(this); } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java index dda3c7f4..2eaa999a 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java @@ -530,7 +530,7 @@ public interface IService { } default QueryWrapperChain queryChain() { - return getMapper().queryChain(); + return new QueryWrapperChain<>(getMapper()); } } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/UpdateChain.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/UpdateChain.java new file mode 100644 index 00000000..92f74779 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/UpdateChain.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.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.mybatisflex.core.update; + +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.exception.FlexExceptions; +import com.mybatisflex.core.mybatis.Mappers; +import com.mybatisflex.core.query.QueryColumn; +import com.mybatisflex.core.query.QueryWrapperAdapter; +import com.mybatisflex.core.util.ClassUtil; +import com.mybatisflex.core.util.LambdaGetter; +import com.mybatisflex.core.util.SqlUtil; +import com.mybatisflex.core.util.UpdateEntity; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +/** + * 用于数据更新、删除的链式操作 + * + * @author michale + * @since 2023-07-25 + */ +public class UpdateChain extends QueryWrapperAdapter> { + + private final BaseMapper baseMapper; + private final T entity; + private final UpdateWrapper entityWrapper; + + public static UpdateChain of(Class entityClass) { + BaseMapper baseMapper = Mappers.ofEntityClass(entityClass); + return new UpdateChain<>(baseMapper); + } + + public UpdateChain(BaseMapper baseMapper) { + this.baseMapper = baseMapper; + this.entity = createEntity(ClassUtil.getUsefulClass(baseMapper.getClass())); + this.entityWrapper = (UpdateWrapper) entity; + } + + private T createEntity(Class mapperClass) { + Type type = mapperClass.getGenericInterfaces()[0]; + if (type instanceof ParameterizedType) { + Class modelClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[0]; + return UpdateEntity.of(modelClass); + } + throw FlexExceptions.wrap("Can not get entity class from mapper: " + mapperClass.getName()); + } + + public static UpdateChain create(BaseMapper baseMapper) { + return new UpdateChain<>(baseMapper); + } + + + public UpdateChain set(String property, Object value) { + entityWrapper.set(property, value); + return this; + } + + + public UpdateChain set(LambdaGetter getter, Object value) { + entityWrapper.set(getter, value); + return this; + } + + + public UpdateChain set(QueryColumn queryColumn, Object value) { + entityWrapper.set(queryColumn, value); + return this; + } + + public UpdateChain setRaw(String property, Object value) { + entityWrapper.setRaw(property, value); + return this; + } + + + public UpdateChain setRaw(LambdaGetter getter, Object value) { + entityWrapper.setRaw(getter, value); + return this; + } + + public UpdateChain setRaw(QueryColumn queryColumn, Object value) { + entityWrapper.set(queryColumn, value); + return this; + } + + + public boolean remove() { + return SqlUtil.toBool(baseMapper.deleteByQuery(this)); + } + + public boolean update() { + return SqlUtil.toBool(baseMapper.updateByQuery(entity, this)); + } + +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/UpdateChainTest.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/UpdateChainTest.java new file mode 100644 index 00000000..48502783 --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/UpdateChainTest.java @@ -0,0 +1,56 @@ +package com.mybatisflex.test; + +import com.mybatisflex.core.MybatisFlexBootstrap; +import com.mybatisflex.core.audit.AuditManager; +import com.mybatisflex.core.audit.ConsoleMessageCollector; +import com.mybatisflex.core.audit.MessageCollector; +import com.mybatisflex.core.update.UpdateChain; +import org.apache.ibatis.logging.stdout.StdOutImpl; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +import javax.sql.DataSource; + +public class UpdateChainTest { + + static AccountMapper accountMapper; + + @BeforeClass + public static void init() { + DataSource dataSource = new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("schema.sql") + .addScript("data.sql") + .build(); + + MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance() + .setDataSource(dataSource) + .setLogImpl(StdOutImpl.class) + .addMapper(AccountMapper.class) + .start(); + + //开启审计功能 + AuditManager.setAuditEnable(true); + + //设置 SQL 审计收集器 + MessageCollector collector = new ConsoleMessageCollector(); + AuditManager.setMessageCollector(collector); + + accountMapper = bootstrap.getMapper(AccountMapper.class); + + } + + @Test + public void testUpdateChain() { + UpdateChain.of(Account.class) + .set(Account::getUserName,"张三") + .setRaw(Account::getAge,"age + 1") + .where(Account::getId).eq(1) + .update(); + + Account account = accountMapper.selectOneById(1); + System.out.println(account); + } +}