diff --git a/src/main/java/META-INF/root-context.xml b/src/main/java/META-INF/root-context.xml
index e215ba63fcd64cd2b6cf92ca29b60cb83fcc2a3b..050bd2316ae4c444ab761a837e24060da98bb592 100644
--- a/src/main/java/META-INF/root-context.xml
+++ b/src/main/java/META-INF/root-context.xml
@@ -140,15 +140,6 @@ along with this program. If not, see .-->
-
-
-
-
-
-
-
-
-
diff --git a/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java b/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java
index 22e9bacb97ac2f45474d0efd9941b130a2fc029d..8958eef6c69ce0b8f716d0ea71196360fb743bae 100644
--- a/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java
+++ b/src/main/java/neatlogic/framework/asynchronization/thread/NeatLogicThread.java
@@ -30,6 +30,7 @@ import java.util.concurrent.Semaphore;
public abstract class NeatLogicThread implements Runnable, Comparable {
private static final Logger logger = LoggerFactory.getLogger(NeatLogicThread.class);
protected UserContext userContext;
+ protected MongodbSessionContext mongodbSessionContext;
private String tenantUuid;
private List activeModuleList;
protected InputFromContext inputFromContext;
@@ -97,6 +98,7 @@ public abstract class NeatLogicThread implements Runnable, Comparable.
+ */
+
+package neatlogic.framework.asynchronization.threadlocal;
+
+import com.mongodb.client.ClientSession;
+
+public class MongodbSessionContext {
+ private ClientSession session;
+ // ThreadLocal 存储当前线程的 Session 对象
+ private static final ThreadLocal sessionThreadLocal = new ThreadLocal<>();
+
+ public static MongodbSessionContext init(ClientSession _session) {
+ MongodbSessionContext context = new MongodbSessionContext();
+ context.setSession(_session);
+ sessionThreadLocal.set(context);
+ return context;
+ }
+
+ public static MongodbSessionContext get() {
+ return sessionThreadLocal.get();
+ }
+
+ public ClientSession getSession() {
+ return session;
+ }
+
+ public void setSession(ClientSession session) {
+ this.session = session;
+ }
+
+ public void release() {
+ sessionThreadLocal.remove();
+ }
+}
diff --git a/src/main/java/neatlogic/framework/common/config/Config.java b/src/main/java/neatlogic/framework/common/config/Config.java
index 4cf235041254f61e35597aa031c8603334a3b98e..28f58e93b9bc13511b2022956bdec6120948e57d 100644
--- a/src/main/java/neatlogic/framework/common/config/Config.java
+++ b/src/main/java/neatlogic/framework/common/config/Config.java
@@ -75,11 +75,6 @@ public class Config {
private static int LOGIN_CAPTCHA_EXPIRED_TIME; //验证码超时时间(秒)
private static int LOGIN_FAILED_TIMES_CAPTCHA; //设置需要验证码的登录错误次数
- private static String MONGO_HOST;
- private static String MONGO_PASSWORD;
- private static String MONGO_USERNAME;
- private static String MONGO_DATABASE;
-
private static String JMS_URL;
private static String KAFKA_URL;
@@ -269,22 +264,6 @@ public class Config {
return DATASOURCE_IDLE_TIMEOUT;
}
- public static String MONGO_HOST() {
- return MONGO_HOST;
- }
-
- public static String MONGO_PASSWORD() {
- return MONGO_PASSWORD;
- }
-
- public static String MONGO_DATABASE() {
- return MONGO_DATABASE;
- }
-
- public static String MONGO_USERNAME() {
- return MONGO_USERNAME;
- }
-
public static String JMS_URL() {
return JMS_URL;
}
@@ -605,10 +584,6 @@ public class Config {
DB_URL = prop.getProperty("db.url");
DB_HOST = prop.getProperty("db.host", "localhost");
DB_PORT = Integer.parseInt(prop.getProperty("db.port", "3306"));
- MONGO_HOST = prop.getProperty("mongo.host", "localhost:27017");
- MONGO_USERNAME = prop.getProperty("mongo.username", "root");
- MONGO_PASSWORD = prop.getProperty("mongo.password", "root");
- MONGO_DATABASE = prop.getProperty("mongo.database", "neatlogic");
JMS_URL = prop.getProperty("jms.url"/*, "tcp://localhost:61616"*/);
KAFKA_URL = prop.getProperty("kafka.url"/*, "localhost:9092"*/);
diff --git a/src/main/java/neatlogic/framework/common/config/LocalConfig.java b/src/main/java/neatlogic/framework/common/config/LocalConfig.java
index 1ac22e6951f88ea7a9ca1c135e884e5b26be5f13..77e8d45cea2657da871e064e4025a0902ccf01eb 100644
--- a/src/main/java/neatlogic/framework/common/config/LocalConfig.java
+++ b/src/main/java/neatlogic/framework/common/config/LocalConfig.java
@@ -180,12 +180,6 @@ public class LocalConfig implements BeanFactoryPostProcessor, EnvironmentAware,
// dbConfigMap.put("conn.testOnBorrow", prop.getProperty("conn.testOnBorrow", "true"));
// dbConfigMap.put("conn.maxIdle", prop.getProperty("conn.maxIdle", "16"));
// dbConfigMap.put("conn.initialSize", prop.getProperty("conn.initialSize", "4"));
- String mongoHost = prop.getProperty("mongo.host", "localhost:27017");
- String mongoUser = prop.getProperty("mongo.username", "root");
- String mongoPwd = prop.getProperty("mongo.password", "root");
- String mongoDb = prop.getProperty("mongo.database", "admin");
- mongoPwd = RC4Util.decrypt(mongoPwd);
- dbConfigMap.put("mongo.url", "mongodb://" + mongoUser + ":" + mongoPwd + "@" + mongoHost + "/" + mongoDb);
dbConfigMap.put("jms.url", prop.getProperty("jms.url", "tcp://localhost:61616"));
dbConfigMap.put("jms.user", prop.getProperty("jms.user", "neatlogic"));
dbConfigMap.put("jms.password", prop.getProperty("jms.password", "123456"));
diff --git a/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml b/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml
index eba7bfc7fa375dffabd3c04bc65c1510c1f19807..6c575380635b9f144c79b94ef6b347f1dff9f7b2 100644
--- a/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml
+++ b/src/main/java/neatlogic/framework/dao/mapper/runner/RunnerMapper.xml
@@ -582,9 +582,8 @@ along with this program. If not, see .-->
- INSERT INTO `runner_map` (`id`, `runner_id`)
+ INSERT IGNORE INTO `runner_map` (`id`, `runner_id`)
VALUES (#{runnerMapId}, #{id})
- ON DUPLICATE KEY UPDATE `runner_id` = #{id} ;
diff --git a/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java b/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java
index 3e46d1b5cc253069ae14b8ada8ddb391958b42b1..ebd4404b13246f0cb50d255ef81808fd5d093c8b 100644
--- a/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java
+++ b/src/main/java/neatlogic/framework/listener/ThreadlocalClearListener.java
@@ -43,6 +43,9 @@ public class ThreadlocalClearListener implements ServletRequestListener {
if (LicensePolicyContext.get() != null) {
LicensePolicyContext.get().release();
}
+ if (MongodbSessionContext.get() != null) {
+ MongodbSessionContext.get().release();
+ }
CacheContext.release();
}
diff --git a/src/main/java/neatlogic/framework/store/mongodb/MongoConfig.java b/src/main/java/neatlogic/framework/store/mongodb/MongoConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b3ad498b96f71dfc41dfe4f0aeff2d65327bcc7
--- /dev/null
+++ b/src/main/java/neatlogic/framework/store/mongodb/MongoConfig.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package neatlogic.framework.store.mongodb;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.mongodb.MongoTransactionManager;
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+@Configuration
+public class MongoConfig {
+
+ @Bean
+ public NeatlogicMongoDatabaseFactory neatlogicMongoDatabaseFactory() {
+ return new NeatlogicMongoDatabaseFactory();
+ }
+
+ @Bean
+ public MongoTemplate mongoTemplate(NeatlogicMongoDatabaseFactory factory) {
+ return new MongoTemplate(factory);
+ }
+
+ @Bean
+ public MongoTransactionManager transactionManagerMongoDb(NeatlogicMongoDatabaseFactory factory) {
+ return new MongoTransactionManager(factory); // 使用标准事务管理器:ml-citation{ref="2,3" data="citationList"}
+ }
+}
diff --git a/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java b/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java
index 4f78b61f0278680567c4939e91248558e4aaf4d0..6f3e5cf39f775c9bc50d3383db507d47e9d46227 100644
--- a/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java
+++ b/src/main/java/neatlogic/framework/store/mongodb/MongoDbManager.java
@@ -15,12 +15,14 @@ along with this program. If not, see .*/
package neatlogic.framework.store.mongodb;
+import com.mongodb.ConnectionString;
+import com.mongodb.MongoClientSettings;
+import com.mongodb.WriteConcern;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import neatlogic.framework.common.RootComponent;
import neatlogic.framework.dao.mapper.MongoDbMapper;
import neatlogic.framework.dto.MongoDbVo;
-import org.apache.commons.lang3.StringUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
@@ -47,7 +49,17 @@ public class MongoDbManager {
}
public static void addDynamicDataSource(MongoDbVo mongoDbVo) {
- MongoClient client = MongoClients.create("mongodb://" + mongoDbVo.getUsername() + ":" + mongoDbVo.getPasswordPlain() + "@" + mongoDbVo.getHost() + "/" + mongoDbVo.getDatabase() + (StringUtils.isNotBlank(mongoDbVo.getOption()) ? "?" + mongoDbVo.getOption() : ""));
+ MongoClientSettings settings = MongoClientSettings.builder()
+ .applyConnectionString(new ConnectionString("mongodb://"
+ + mongoDbVo.getUsername() + ":"
+ + mongoDbVo.getPasswordPlain() + "@"
+ + mongoDbVo.getHost() + "/"
+ + mongoDbVo.getDatabase() + "?"
+ + mongoDbVo.getOption()))
+ .writeConcern(WriteConcern.MAJORITY) // 添加这一行
+ .build();
+ MongoClient client = MongoClients.create(settings);
+
mongoDbMap.put(mongoDbVo.getTenantUuid(), client);
mongoDatabaseMap.put(mongoDbVo.getTenantUuid(), mongoDbVo.getDatabase());
}
diff --git a/src/main/java/neatlogic/framework/store/mongodb/NeatLogicMongoDbFactory.java b/src/main/java/neatlogic/framework/store/mongodb/NeatLogicMongoDbFactory.java
deleted file mode 100644
index 1a3fc2204cf08e4b237bce534baa473e15224cf1..0000000000000000000000000000000000000000
--- a/src/main/java/neatlogic/framework/store/mongodb/NeatLogicMongoDbFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*Copyright (C) 2024 深圳极向量科技有限公司 All Rights Reserved.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .*/
-
-package neatlogic.framework.store.mongodb;
-
-import com.mongodb.client.MongoDatabase;
-import neatlogic.framework.asynchronization.threadlocal.TenantContext;
-import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
-
-public class NeatLogicMongoDbFactory extends SimpleMongoClientDatabaseFactory {
-
- public NeatLogicMongoDbFactory(String connectionString) {
- super(connectionString);
- }
-
-
- @Override
- protected MongoDatabase doGetMongoDatabase(String dbName) {
- return MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid()).getDatabase(MongoDbManager.getDatabase(TenantContext.get().getTenantUuid()));
- }
-
-
-}
diff --git a/src/main/java/neatlogic/framework/store/mongodb/NeatlogicMongoDatabaseFactory.java b/src/main/java/neatlogic/framework/store/mongodb/NeatlogicMongoDatabaseFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6a4b17a778c642f8a3a14c8406d1855867129e0
--- /dev/null
+++ b/src/main/java/neatlogic/framework/store/mongodb/NeatlogicMongoDatabaseFactory.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package neatlogic.framework.store.mongodb;
+
+import com.mongodb.ClientSessionOptions;
+import com.mongodb.client.ClientSession;
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoDatabase;
+import neatlogic.framework.asynchronization.threadlocal.TenantContext;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.data.mongodb.MongoDatabaseFactory;
+import org.springframework.data.mongodb.core.MongoExceptionTranslator;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Component;
+
+@Component
+@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
+public class NeatlogicMongoDatabaseFactory implements MongoDatabaseFactory {
+
+ @Override
+ public @NonNull MongoDatabase getMongoDatabase() {
+ return getMongoDatabase(MongoDbManager.getDatabase(TenantContext.get().getTenantUuid()));
+ }
+
+ @Override
+ public @NonNull MongoDatabase getMongoDatabase(@NonNull String dbName) {
+ return MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid()).getDatabase(dbName);
+ }
+
+ @Override
+ public @NonNull ClientSession getSession(@NonNull ClientSessionOptions options) {
+ // 确保 MongoClient 是从租户管理中获取的
+ return MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid()).startSession(options);
+ }
+
+ @Override
+ public @NonNull MongoExceptionTranslator getExceptionTranslator() {
+ return new MongoExceptionTranslator();
+ }
+
+ @Override
+ public @NonNull MongoDatabaseFactory withSession(@NonNull ClientSession session) {
+ MongoClient mongoClient = MongoDbManager.getMongoClient(TenantContext.get().getTenantUuid());
+
+ return new MongoDatabaseFactory() {
+ @Override
+ public @NonNull MongoDatabase getMongoDatabase() {
+ return getMongoDatabase(MongoDbManager.getDatabase(TenantContext.get().getTenantUuid()));
+ }
+
+ @Override
+ public @NonNull MongoDatabase getMongoDatabase(@NonNull String dbName) {
+ return mongoClient.getDatabase(dbName);
+ }
+
+ @Override
+ public @NonNull ClientSession getSession(@NonNull ClientSessionOptions options) {
+ return session;
+ }
+
+ @Override
+ public @NonNull MongoExceptionTranslator getExceptionTranslator() {
+ return new MongoExceptionTranslator();
+ }
+
+ @Override
+ public @NonNull MongoDatabaseFactory withSession(@NonNull ClientSession session) {
+ return this;
+ }
+ };
+ }
+}
+