From 023dea2441b161fc9f0b714fffa56202e7d995f1 Mon Sep 17 00:00:00 2001 From: Tyke Chen <190473011+chentyke@users.noreply.github.com> Date: Mon, 13 Jul 2026 10:45:27 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E6=BA=90=E7=B1=BB=E5=9E=8B=E5=A4=84=E7=90=86=E5=99=A8?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/manager-api/pom.xml | 52 ++++++++++++++- .../common/service/impl/BaseServiceImpl.java | 8 ++- .../agent/service/AgentChatAudioService.java | 5 +- .../service/AgentChatHistoryService.java | 7 +- .../service/AgentPluginMappingService.java | 5 +- .../agent/service/AgentTemplateService.java | 5 +- .../impl/AgentChatAudioServiceImpl.java | 5 +- .../impl/AgentChatHistoryServiceImpl.java | 5 +- .../impl/AgentPluginMappingServiceImpl.java | 5 +- .../impl/AgentTemplateServiceImpl.java | 5 +- .../impl/AgentVoicePrintServiceImpl.java | 5 +- .../ContextProviderListTypeHandler.java | 44 ++++++++++--- .../xiaozhi/common/mybatisplus/MpService.java | 7 ++ .../common/mybatisplus/MpServiceImpl.java | 10 +++ .../mybatisplus/MybatisPlusBatchHelper.java | 24 +++++++ .../xiaozhi/common/mybatisplus/MpService.java | 7 ++ .../common/mybatisplus/MpServiceImpl.java | 10 +++ .../mybatisplus/MybatisPlusBatchHelper.java | 27 ++++++++ .../MybatisPlusBatchHelperTest.java | 47 ++++++++++++++ .../impl/AgentSnapshotServiceImplTest.java | 16 ++--- .../ContextProviderListTypeHandlerTest.java | 65 ++++++++++++++----- 21 files changed, 298 insertions(+), 66 deletions(-) create mode 100644 main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpService.java create mode 100644 main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpServiceImpl.java create mode 100644 main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java create mode 100644 main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpService.java create mode 100644 main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpServiceImpl.java create mode 100644 main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java create mode 100644 main/manager-api/src/test/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelperTest.java diff --git a/main/manager-api/pom.xml b/main/manager-api/pom.xml index 5981f4b2..098b0cef 100644 --- a/main/manager-api/pom.xml +++ b/main/manager-api/pom.xml @@ -21,6 +21,9 @@ 5.10.1 1.2.20 3.5.5 + mybatis-plus-boot-starter + 3.0.3 + src/mybatis-plus-legacy/java 5.8.24 1.19.1 4.6.0 @@ -176,13 +179,13 @@ com.baomidou - mybatis-plus-boot-starter + ${mybatisplus.starter.artifactId} ${mybatisplus.version} org.mybatis mybatis-spring - 3.0.3 + ${mybatis-spring.version} cn.hutool @@ -265,9 +268,54 @@ + + + + mybatis-plus-3.5.6 + + 3.5.6 + + + + + mybatis-plus-3.5.17 + + 3.5.17 + mybatis-plus-spring-boot3-starter + 3.0.5 + src/mybatis-plus-modern/java + + + + com.baomidou + mybatis-plus-jsqlparser-4.9 + ${mybatisplus.version} + + + + ${project.artifactId} + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + add-mybatis-plus-compatibility-sources + generate-sources + + add-source + + + + ${project.basedir}/${mybatisplus.compat.source} + + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/main/manager-api/src/main/java/xiaozhi/common/service/impl/BaseServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/common/service/impl/BaseServiceImpl.java index 9d06c09a..c373b02b 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/service/impl/BaseServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/common/service/impl/BaseServiceImpl.java @@ -27,6 +27,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; import xiaozhi.common.constant.Constant; +import xiaozhi.common.mybatisplus.MybatisPlusBatchHelper; import xiaozhi.common.page.PageData; import xiaozhi.common.service.BaseService; import xiaozhi.common.utils.ConvertUtils; @@ -181,8 +182,9 @@ public abstract class BaseServiceImpl, T> implements Bas * 执行批量操作 */ @SuppressWarnings("deprecation") - protected boolean executeBatch(Collection list, int batchSize, BiConsumer consumer) { - return SqlHelper.executeBatch(this.currentModelClass(), this.log, list, batchSize, consumer); + protected boolean executeBatch(Collection list, int batchSize, BiConsumer operation) { + return MybatisPlusBatchHelper.executeBatch(SqlHelper.sqlSessionFactory(this.currentModelClass()), this.log, + list, batchSize, operation); } @Override @@ -227,4 +229,4 @@ public abstract class BaseServiceImpl, T> implements Bas public boolean deleteBatchIds(Collection idList) { return SqlHelper.retBool(baseDao.deleteBatchIds(idList)); } -} \ No newline at end of file +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatAudioService.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatAudioService.java index 04be9f36..d7597243 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatAudioService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatAudioService.java @@ -1,7 +1,6 @@ package xiaozhi.modules.agent.service; -import com.baomidou.mybatisplus.extension.service.IService; - +import xiaozhi.common.mybatisplus.MpService; import xiaozhi.modules.agent.entity.AgentChatAudioEntity; /** @@ -11,7 +10,7 @@ import xiaozhi.modules.agent.entity.AgentChatAudioEntity; * @version 1.0, 2025/5/8 * @since 1.0.0 */ -public interface AgentChatAudioService extends IService { +public interface AgentChatAudioService extends MpService { /** * 保存音频数据 * diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatHistoryService.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatHistoryService.java index 48fc0539..261cf161 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatHistoryService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentChatHistoryService.java @@ -3,9 +3,8 @@ package xiaozhi.modules.agent.service; import java.util.List; import java.util.Map; -import com.baomidou.mybatisplus.extension.service.IService; - -import xiaozhi.common.page.PageData; +import xiaozhi.common.page.PageData; +import xiaozhi.common.mybatisplus.MpService; import xiaozhi.modules.agent.dto.AgentChatHistoryDTO; import xiaozhi.modules.agent.dto.AgentChatSessionDTO; import xiaozhi.modules.agent.entity.AgentChatHistoryEntity; @@ -18,7 +17,7 @@ import xiaozhi.modules.agent.vo.AgentChatHistoryUserVO; * @version 1.0, 2025/4/30 * @since 1.0.0 */ -public interface AgentChatHistoryService extends IService { +public interface AgentChatHistoryService extends MpService { /** * 根据智能体ID获取会话列表 diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentPluginMappingService.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentPluginMappingService.java index 9411cc80..25beb9cc 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentPluginMappingService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentPluginMappingService.java @@ -2,15 +2,14 @@ package xiaozhi.modules.agent.service; import java.util.List; -import com.baomidou.mybatisplus.extension.service.IService; - +import xiaozhi.common.mybatisplus.MpService; import xiaozhi.modules.agent.entity.AgentPluginMapping; /** * @description 针对表【ai_agent_plugin_mapping(Agent与插件的唯一映射表)】的数据库操作Service * @createDate 2025-05-25 22:33:17 */ -public interface AgentPluginMappingService extends IService { +public interface AgentPluginMappingService extends MpService { /** * 根据智能体id获取插件参数 diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentTemplateService.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentTemplateService.java index b10a67f9..09f4a4bd 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentTemplateService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentTemplateService.java @@ -1,7 +1,6 @@ package xiaozhi.modules.agent.service; -import com.baomidou.mybatisplus.extension.service.IService; - +import xiaozhi.common.mybatisplus.MpService; import xiaozhi.modules.agent.entity.AgentTemplateEntity; /** @@ -9,7 +8,7 @@ import xiaozhi.modules.agent.entity.AgentTemplateEntity; * @description 针对表【ai_agent_template(智能体配置模板表)】的数据库操作Service * @createDate 2025-03-22 11:48:18 */ -public interface AgentTemplateService extends IService { +public interface AgentTemplateService extends MpService { /** * 获取默认模板 diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatAudioServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatAudioServiceImpl.java index efcae485..0799446c 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatAudioServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatAudioServiceImpl.java @@ -2,8 +2,7 @@ package xiaozhi.modules.agent.service.impl; import org.springframework.stereotype.Service; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - +import xiaozhi.common.mybatisplus.MpServiceImpl; import xiaozhi.modules.agent.dao.AiAgentChatAudioDao; import xiaozhi.modules.agent.entity.AgentChatAudioEntity; import xiaozhi.modules.agent.service.AgentChatAudioService; @@ -16,7 +15,7 @@ import xiaozhi.modules.agent.service.AgentChatAudioService; * @since 1.0.0 */ @Service -public class AgentChatAudioServiceImpl extends ServiceImpl +public class AgentChatAudioServiceImpl extends MpServiceImpl implements AgentChatAudioService { @Override public String saveAudio(byte[] audioData) { diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatHistoryServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatHistoryServiceImpl.java index d2e8e905..ff4c7126 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatHistoryServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentChatHistoryServiceImpl.java @@ -14,9 +14,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - import xiaozhi.common.constant.Constant; +import xiaozhi.common.mybatisplus.MpServiceImpl; import xiaozhi.common.page.PageData; import xiaozhi.common.utils.ConvertUtils; import xiaozhi.common.utils.JsonUtils; @@ -39,7 +38,7 @@ import xiaozhi.modules.agent.vo.AgentChatHistoryUserVO; */ @Service @RequiredArgsConstructor -public class AgentChatHistoryServiceImpl extends ServiceImpl +public class AgentChatHistoryServiceImpl extends MpServiceImpl implements AgentChatHistoryService { private final AgentChatTitleService agentChatTitleService; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java index a8784010..4305cf6c 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentPluginMappingServiceImpl.java @@ -9,11 +9,10 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import xiaozhi.common.utils.JsonUtils; +import xiaozhi.common.mybatisplus.MpServiceImpl; import xiaozhi.modules.agent.dao.AgentPluginMappingMapper; import xiaozhi.modules.agent.entity.AgentPluginMapping; import xiaozhi.modules.agent.service.AgentPluginMappingService; @@ -29,7 +28,7 @@ import xiaozhi.modules.model.service.ModelConfigService; @Service @RequiredArgsConstructor @Slf4j -public class AgentPluginMappingServiceImpl extends ServiceImpl +public class AgentPluginMappingServiceImpl extends MpServiceImpl implements AgentPluginMappingService { private final AgentPluginMappingMapper agentPluginMappingMapper; private final KnowledgeBaseService knowledgeBaseService; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java index 321b5cb2..b52666d5 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTemplateServiceImpl.java @@ -4,8 +4,7 @@ import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - +import xiaozhi.common.mybatisplus.MpServiceImpl; import xiaozhi.modules.agent.dao.AgentTemplateDao; import xiaozhi.modules.agent.entity.AgentTemplateEntity; import xiaozhi.modules.agent.service.AgentTemplateService; @@ -21,7 +20,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; * @createDate 2025-03-22 11:48:18 */ @Service -public class AgentTemplateServiceImpl extends ServiceImpl +public class AgentTemplateServiceImpl extends MpServiceImpl implements AgentTemplateService { /** diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java index 088e4663..21314f52 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java @@ -22,12 +22,11 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; - import lombok.extern.slf4j.Slf4j; import xiaozhi.common.constant.Constant; import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.RenException; +import xiaozhi.common.mybatisplus.MpServiceImpl; import xiaozhi.common.utils.ConvertUtils; import xiaozhi.common.utils.JsonUtils; import xiaozhi.modules.agent.dao.AgentVoicePrintDao; @@ -46,7 +45,7 @@ import xiaozhi.modules.sys.service.SysParamsService; */ @Service @Slf4j -public class AgentVoicePrintServiceImpl extends ServiceImpl +public class AgentVoicePrintServiceImpl extends MpServiceImpl implements AgentVoicePrintService { private final AgentChatAudioService agentChatAudioService; private final RestTemplate restTemplate; diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandler.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandler.java index f0762e35..4f701233 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandler.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandler.java @@ -1,31 +1,59 @@ package xiaozhi.modules.agent.typehandler; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.Collections; import java.util.List; import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; -import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; import com.fasterxml.jackson.core.type.TypeReference; import xiaozhi.common.utils.JsonUtils; import xiaozhi.modules.agent.dto.ContextProviderDTO; -public class ContextProviderListTypeHandler extends AbstractJsonTypeHandler> { +/** + * JSON type handler for context providers. + * + *

Do not extend MyBatis-Plus {@code AbstractJsonTypeHandler}: its constructor and JSON handler + * contract changed in MyBatis-Plus 3.5.6. {@link BaseTypeHandler} is part of MyBatis itself and + * keeps this handler compatible with both 3.5.5 and newer MyBatis-Plus releases.

+ */ +public class ContextProviderListTypeHandler extends BaseTypeHandler> { private static final TypeReference> CONTEXT_PROVIDER_LIST_TYPE = new TypeReference<>() { }; @Override - protected List parse(String json) { + public void setNonNullParameter(PreparedStatement ps, int i, List parameter, + JdbcType jdbcType) throws SQLException { + ps.setString(i, JsonUtils.toJsonString(parameter)); + } + + @Override + public List getNullableResult(ResultSet rs, String columnName) throws SQLException { + return parseNullable(rs.getString(columnName)); + } + + @Override + public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return parseNullable(rs.getString(columnIndex)); + } + + @Override + public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return parseNullable(cs.getString(columnIndex)); + } + + private List parseNullable(String json) { if (StringUtils.isBlank(json)) { - return Collections.emptyList(); + return null; } List providers = JsonUtils.parseObject(json, CONTEXT_PROVIDER_LIST_TYPE); return providers == null ? Collections.emptyList() : providers; } - @Override - protected String toJson(List obj) { - return JsonUtils.toJsonString(obj == null ? Collections.emptyList() : obj); - } } diff --git a/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpService.java b/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpService.java new file mode 100644 index 00000000..65e5c8b9 --- /dev/null +++ b/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpService.java @@ -0,0 +1,7 @@ +package xiaozhi.common.mybatisplus; + +/** + * Stable project-level alias for the MyBatis-Plus service contract used by 3.5.5 and 3.5.6. + */ +public interface MpService extends com.baomidou.mybatisplus.extension.service.IService { +} diff --git a/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpServiceImpl.java b/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpServiceImpl.java new file mode 100644 index 00000000..421588fb --- /dev/null +++ b/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MpServiceImpl.java @@ -0,0 +1,10 @@ +package xiaozhi.common.mybatisplus; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * Stable project-level base class for the MyBatis-Plus 3.5.5/3.5.6 service implementation. + */ +public class MpServiceImpl, T> + extends com.baomidou.mybatisplus.extension.service.impl.ServiceImpl implements MpService { +} diff --git a/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java b/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java new file mode 100644 index 00000000..2350f24e --- /dev/null +++ b/main/manager-api/src/mybatis-plus-legacy/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java @@ -0,0 +1,24 @@ +package xiaozhi.common.mybatisplus; + +import java.util.Collection; +import java.util.function.BiConsumer; + +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; + +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; + +/** + * Type-safe access to the MyBatis-Plus 3.5.5/3.5.6 batch callback API. + */ +public final class MybatisPlusBatchHelper { + private MybatisPlusBatchHelper() { + } + + @SuppressWarnings("deprecation") + public static boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Collection entities, + int batchSize, BiConsumer operation) { + return SqlHelper.executeBatch(sqlSessionFactory, log, entities, batchSize, operation); + } +} diff --git a/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpService.java b/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpService.java new file mode 100644 index 00000000..23bfeca6 --- /dev/null +++ b/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpService.java @@ -0,0 +1,7 @@ +package xiaozhi.common.mybatisplus; + +/** + * Stable project-level alias for the MyBatis-Plus 3.5.17 Spring service contract. + */ +public interface MpService extends com.baomidou.mybatisplus.spring.service.IService { +} diff --git a/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpServiceImpl.java b/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpServiceImpl.java new file mode 100644 index 00000000..fd1fb2f6 --- /dev/null +++ b/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MpServiceImpl.java @@ -0,0 +1,10 @@ +package xiaozhi.common.mybatisplus; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * Stable project-level base class for the MyBatis-Plus 3.5.17 Spring service implementation. + */ +public class MpServiceImpl, T> + extends com.baomidou.mybatisplus.spring.service.impl.ServiceImpl implements MpService { +} diff --git a/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java b/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java new file mode 100644 index 00000000..690fee97 --- /dev/null +++ b/main/manager-api/src/mybatis-plus-modern/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelper.java @@ -0,0 +1,27 @@ +package xiaozhi.common.mybatisplus; + +import java.util.Collection; +import java.util.function.BiConsumer; + +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; + +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; + +/** + * Type-safe access to the MyBatis-Plus 3.5.17 batch callback API. + */ +public final class MybatisPlusBatchHelper { + private MybatisPlusBatchHelper() { + } + + @SuppressWarnings("deprecation") + public static boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Collection entities, + int batchSize, BiConsumer operation) { + return SqlHelper.executeBatch(sqlSessionFactory, log, entities, batchSize, (sqlSession, entity) -> { + operation.accept(sqlSession, entity); + return 0; + }); + } +} diff --git a/main/manager-api/src/test/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelperTest.java b/main/manager-api/src/test/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelperTest.java new file mode 100644 index 00000000..692d56c7 --- /dev/null +++ b/main/manager-api/src/test/java/xiaozhi/common/mybatisplus/MybatisPlusBatchHelperTest.java @@ -0,0 +1,47 @@ +package xiaozhi.common.mybatisplus; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.ibatis.executor.BatchResult; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.junit.jupiter.api.Test; + +class MybatisPlusBatchHelperTest { + + @Test + void executesBatchThroughSelectedVersionAdapter() { + SqlSessionFactory sqlSessionFactory = mock(SqlSessionFactory.class); + SqlSession sqlSession = mock(SqlSession.class); + Log log = mock(Log.class); + when(sqlSessionFactory.openSession(ExecutorType.BATCH)).thenReturn(sqlSession); + + BatchResult batchResult = new BatchResult(mock(MappedStatement.class), "INSERT"); + batchResult.setUpdateCounts(new int[] { 1, 1 }); + when(sqlSession.flushStatements()).thenReturn(List.of(batchResult)); + + List processed = new ArrayList<>(); + boolean result = MybatisPlusBatchHelper.executeBatch(sqlSessionFactory, log, List.of("first", "second"), 2, + (session, entity) -> { + assertSame(sqlSession, session); + processed.add(entity); + }); + + assertTrue(result); + assertEquals(List.of("first", "second"), processed); + verify(sqlSession).flushStatements(); + verify(sqlSession).commit(true); + verify(sqlSession).close(); + } +} diff --git a/main/manager-api/src/test/java/xiaozhi/modules/agent/service/impl/AgentSnapshotServiceImplTest.java b/main/manager-api/src/test/java/xiaozhi/modules/agent/service/impl/AgentSnapshotServiceImplTest.java index 78fd05b9..c822358c 100644 --- a/main/manager-api/src/test/java/xiaozhi/modules/agent/service/impl/AgentSnapshotServiceImplTest.java +++ b/main/manager-api/src/test/java/xiaozhi/modules/agent/service/impl/AgentSnapshotServiceImplTest.java @@ -1096,13 +1096,13 @@ class AgentSnapshotServiceImplTest { when(snapshotService.getCurrentVersionNo(agentId)).thenReturn(0); when(contextProviderService.getByAgentId(agentId)).thenReturn(null); when(correctWordFileService.getAgentCorrectWordFileIds(agentId)).thenReturn(List.of()); - when(agentDao.updateById(any())).thenReturn(1); + when(agentDao.updateById(any(AgentEntity.class))).thenReturn(1); service.updateAgentById(agentId, update); InOrder inOrder = inOrder(agentDao, snapshotService); inOrder.verify(snapshotService).createSnapshot(agentId, "initial"); - inOrder.verify(agentDao).updateById(argThat(agent -> "new-name".equals(agent.getAgentName()))); + inOrder.verify(agentDao).updateById(argThat((AgentEntity agent) -> "new-name".equals(agent.getAgentName()))); inOrder.verify(snapshotService).createSnapshot(agentId, "config"); } @@ -1130,13 +1130,13 @@ class AgentSnapshotServiceImplTest { when(snapshotService.getCurrentVersionNo(agentId)).thenReturn(4); when(contextProviderService.getByAgentId(agentId)).thenReturn(null); when(correctWordFileService.getAgentCorrectWordFileIds(agentId)).thenReturn(List.of()); - when(agentDao.updateById(any())).thenReturn(1); + when(agentDao.updateById(any(AgentEntity.class))).thenReturn(1); service.updateAgentById(agentId, update); InOrder inOrder = inOrder(agentDao, snapshotService); inOrder.verify(snapshotService).createSnapshot(agentId, "current"); - inOrder.verify(agentDao).updateById(argThat(agent -> "new-name".equals(agent.getAgentName()))); + inOrder.verify(agentDao).updateById(argThat((AgentEntity agent) -> "new-name".equals(agent.getAgentName()))); inOrder.verify(snapshotService).createSnapshot(agentId, "config"); } @@ -1160,7 +1160,7 @@ class AgentSnapshotServiceImplTest { when(templateService.getDefaultTemplate()).thenReturn(template); when(timbreService.getDefaultLanguageById("TTS_EdgeTTS0001")).thenReturn("普通话"); - when(agentDao.insert(any())).thenReturn(1); + when(agentDao.insert(any(AgentEntity.class))).thenReturn(1); AgentCreateDTO dto = new AgentCreateDTO(); dto.setAgentName("test123"); @@ -1168,7 +1168,7 @@ class AgentSnapshotServiceImplTest { String agentId = service.createAgent(dto); InOrder inOrder = inOrder(agentDao, pluginMappingService, snapshotService); - inOrder.verify(agentDao).insert(argThat(agent -> "test123".equals(agent.getAgentName()) + inOrder.verify(agentDao).insert(argThat((AgentEntity agent) -> "test123".equals(agent.getAgentName()) && "普通话".equals(agent.getTtsLanguage()) && "".equals(agent.getSummaryMemory()) && Integer.valueOf(0).equals(agent.getChatHistoryConf()))); @@ -1834,8 +1834,8 @@ class AgentSnapshotServiceImplTest { assertTrue(error.getCause() instanceof RenException); assertEquals("快照引用的标签已被删除,无法恢复,请先重新创建或选择标签", error.getCause().getMessage()); - verify(tagDao, never()).updateById(any()); - verify(tagDao, never()).insert(any()); + verify(tagDao, never()).updateById(any(AgentTagEntity.class)); + verify(tagDao, never()).insert(any(AgentTagEntity.class)); } private AgentInfoVO snapshotAgentInfo(String agentId, Long userId, String agentName, String summaryMemory) { diff --git a/main/manager-api/src/test/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandlerTest.java b/main/manager-api/src/test/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandlerTest.java index e1d0e6c4..95c9b154 100644 --- a/main/manager-api/src/test/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandlerTest.java +++ b/main/manager-api/src/test/java/xiaozhi/modules/agent/typehandler/ContextProviderListTypeHandlerTest.java @@ -2,36 +2,30 @@ package xiaozhi.modules.agent.typehandler; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.util.List; import org.apache.ibatis.type.TypeHandler; import org.apache.ibatis.type.TypeHandlerRegistry; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import com.fasterxml.jackson.core.type.TypeReference; + +import xiaozhi.common.utils.JsonUtils; import xiaozhi.modules.agent.dto.ContextProviderDTO; class ContextProviderListTypeHandlerTest { private final ContextProviderListTypeHandler handler = new ContextProviderListTypeHandler(); - @Test - void parseKeepsContextProviderDtoElementType() { - List providers = handler - .parse("[{\"url\":\"https://example.com/context\",\"headers\":{\"Authorization\":\"Bearer token\"}}]"); - - assertEquals(1, providers.size()); - assertInstanceOf(ContextProviderDTO.class, providers.get(0)); - assertEquals("https://example.com/context", providers.get(0).getUrl()); - assertEquals("Bearer token", providers.get(0).getHeaders().get("Authorization")); - } - - @Test - void parseBlankJsonAsEmptyList() { - assertTrue(handler.parse(" ").isEmpty()); - } - @Test void myBatisCanInstantiateHandlerForListField() { TypeHandler typeHandler = new TypeHandlerRegistry().getInstance(List.class, @@ -39,4 +33,41 @@ class ContextProviderListTypeHandlerTest { assertInstanceOf(ContextProviderListTypeHandler.class, typeHandler); } + + @Test + void resultSetDeserializationKeepsContextProviderDtoElementType() throws Exception { + ResultSet resultSet = mock(ResultSet.class); + when(resultSet.getString("context_providers")) + .thenReturn("[{\"url\":\"https://example.com/context\",\"headers\":{\"Authorization\":\"Bearer token\"}}]"); + + List providers = handler.getNullableResult(resultSet, "context_providers"); + + assertEquals(1, providers.size()); + assertInstanceOf(ContextProviderDTO.class, providers.get(0)); + assertEquals("https://example.com/context", providers.get(0).getUrl()); + assertEquals("Bearer token", providers.get(0).getHeaders().get("Authorization")); + } + + @Test + void sqlNullRemainsNull() throws Exception { + ResultSet resultSet = mock(ResultSet.class); + + assertNull(handler.getNullableResult(resultSet, 1)); + } + + @Test + void serializesProviderListAsJson() throws Exception { + ContextProviderDTO provider = new ContextProviderDTO(); + provider.setUrl("https://example.com/context"); + PreparedStatement statement = mock(PreparedStatement.class); + + handler.setNonNullParameter(statement, 1, List.of(provider), null); + + ArgumentCaptor json = ArgumentCaptor.forClass(String.class); + verify(statement).setString(eq(1), json.capture()); + List serialized = JsonUtils.parseObject(json.getValue(), new TypeReference<>() { + }); + assertEquals(1, serialized.size()); + assertEquals("https://example.com/context", serialized.get(0).getUrl()); + } }