From 39ea6f1e4105eef4cd97257f5941f89d6ff91e67 Mon Sep 17 00:00:00 2001 From: lhpqaq <657407891@qq.com> Date: Fri, 20 Sep 2024 18:00:31 +0800 Subject: [PATCH] Squashed commit of the following: commit 4cce0646a145f2a9e94e1a48b899d35d7a2b1119 Author: haopeng <657407891@qq.com> Date: Fri Sep 20 14:22:07 2024 +0800 BIGTOP-4230: Add some methods for BaseDao (#74) commit 103b8cfc23de373bfb94cb0622b3f88d097c1724 Author: timyuer <524860213@qq.com> Date: Fri Sep 20 09:56:29 2024 +0800 BIGTOP-4145: Improve docker development support scripts (#73) --- .../dao/interceptor/AuditingInterceptor.java | 4 +- .../bigtop/manager/dao/po/ChatMessagePO.java | 6 +- .../bigtop/manager/dao/po/ChatThreadPO.java | 6 +- .../apache/bigtop/manager/dao/po/HostPO.java | 2 +- .../apache/bigtop/manager/dao/po/JobPO.java | 4 +- .../manager/dao/po/PlatformAuthorizedPO.java | 2 +- .../apache/bigtop/manager/dao/po/RepoPO.java | 2 +- .../apache/bigtop/manager/dao/po/StackPO.java | 4 +- .../apache/bigtop/manager/dao/po/StagePO.java | 6 +- .../apache/bigtop/manager/dao/po/TaskPO.java | 2 +- .../manager/dao/repository/BaseDao.java | 27 +- .../manager/dao/repository/HostDao.java | 2 - .../manager/dao/repository/RepoDao.java | 2 - .../manager/dao/sql/BaseSqlProvider.java | 53 ++- .../bigtop/manager/dao/sql/SQLBuilder.java | 360 +++++++++++++++++- .../resources/mapper/mysql/HostMapper.xml | 8 - .../resources/mapper/mysql/RepoMapper.xml | 8 - .../mapper/postgresql/HostMapper.xml | 8 - .../mapper/postgresql/RepoMapper.xml | 8 - .../server/command/job/AbstractJob.java | 6 +- .../server/command/job/ClusterCreateJob.java | 8 +- .../server/command/stage/AbstractStage.java | 6 +- .../server/command/task/AbstractTask.java | 6 +- .../command/task/ComponentInstallTask.java | 2 +- .../command/task/ComponentStartTask.java | 2 +- .../command/task/ComponentStopTask.java | 2 +- .../scheduler/ComponentStatusScheduler.java | 4 +- .../server/scheduler/HostInfoScheduler.java | 2 +- .../service/impl/ClusterServiceImpl.java | 4 +- .../service/impl/ConfigServiceImpl.java | 2 +- .../server/service/impl/HostServiceImpl.java | 2 +- .../server/service/impl/JobServiceImpl.java | 6 +- .../server/service/impl/UserServiceImpl.java | 2 +- dev-support/README.md | 23 +- dev-support/docker/centos7/Dockerfile | 32 -- .../docker/centos7/build-containers.sh | 111 ------ dev-support/docker/centos7/build-image.sh | 30 -- .../docker/centos7/clear-containers.sh | 38 -- .../docker/centos7/distribute-scripts.sh | 35 -- dev-support/docker/containers/build.sh | 226 +++++++++++ .../Dockerfile => image/Dockerfile.template} | 6 +- dev-support/docker/image/build.sh | 78 ++++ dev-support/docker/openeuler22/Dockerfile | 33 -- .../docker/openeuler22/build-containers.sh | 133 ------- dev-support/docker/openeuler22/build-image.sh | 30 -- .../docker/openeuler22/clear-containers.sh | 40 -- .../docker/openeuler22/distribute-scripts.sh | 35 -- .../docker/openeuler22/restart-containers.sh | 43 --- dev-support/docker/rocky8/build-containers.sh | 132 ------- dev-support/docker/rocky8/build-image.sh | 30 -- dev-support/docker/rocky8/clear-containers.sh | 40 -- .../docker/rocky8/distribute-scripts.sh | 35 -- .../docker/rocky8/restart-containers.sh | 43 --- dev-support/example/bigtop_manager/user.sql | 20 - 54 files changed, 781 insertions(+), 980 deletions(-) delete mode 100644 dev-support/docker/centos7/Dockerfile delete mode 100755 dev-support/docker/centos7/build-containers.sh delete mode 100755 dev-support/docker/centos7/build-image.sh delete mode 100755 dev-support/docker/centos7/clear-containers.sh delete mode 100755 dev-support/docker/centos7/distribute-scripts.sh create mode 100644 dev-support/docker/containers/build.sh rename dev-support/docker/{rocky8/Dockerfile => image/Dockerfile.template} (97%) create mode 100644 dev-support/docker/image/build.sh delete mode 100644 dev-support/docker/openeuler22/Dockerfile delete mode 100755 dev-support/docker/openeuler22/build-containers.sh delete mode 100755 dev-support/docker/openeuler22/build-image.sh delete mode 100755 dev-support/docker/openeuler22/clear-containers.sh delete mode 100755 dev-support/docker/openeuler22/distribute-scripts.sh delete mode 100755 dev-support/docker/openeuler22/restart-containers.sh delete mode 100755 dev-support/docker/rocky8/build-containers.sh delete mode 100755 dev-support/docker/rocky8/build-image.sh delete mode 100755 dev-support/docker/rocky8/clear-containers.sh delete mode 100755 dev-support/docker/rocky8/distribute-scripts.sh delete mode 100755 dev-support/docker/rocky8/restart-containers.sh delete mode 100644 dev-support/example/bigtop_manager/user.sql diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/interceptor/AuditingInterceptor.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/interceptor/AuditingInterceptor.java index 376994afc..d1782fc17 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/interceptor/AuditingInterceptor.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/interceptor/AuditingInterceptor.java @@ -73,7 +73,9 @@ public Object intercept(Invocation invocation) throws Throwable { Collection objects; if (parameter instanceof MapperMethod.ParamMap) { MapperMethod.ParamMap paramMap = ((MapperMethod.ParamMap) parameter); - if (paramMap.get("param1") instanceof Collection) { + if (!paramMap.containsKey("param1") && paramMap.containsKey("arg0")) { + objects = ((Collection) paramMap.get("arg0")); + } else if (paramMap.get("param1") instanceof Collection) { objects = ((Collection) paramMap.get("param1")); } else { objects = Collections.singletonList(paramMap.get("param1")); diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatMessagePO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatMessagePO.java index 92ee273d3..e84414bda 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatMessagePO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatMessagePO.java @@ -37,13 +37,13 @@ public class ChatMessagePO extends BasePO implements Serializable { @Column(name = "message", nullable = false, length = 255) private String message; - @Column(name = "sender") + @Column(name = "sender", nullable = false) private String sender; - @Column(name = "user_id") + @Column(name = "user_id", nullable = false) private Long userId; - @Column(name = "thread_id") + @Column(name = "thread_id", nullable = false) private Long threadId; @Column(name = "is_deleted") diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java index 92e9a30e9..08a9e4b0b 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/ChatThreadPO.java @@ -38,13 +38,13 @@ public class ChatThreadPO extends BasePO implements Serializable { @Column(name = "model", nullable = false, length = 255) private String model; - @Column(name = "thread_info", columnDefinition = "json", nullable = false) + @Column(name = "thread_info", columnDefinition = "json") private Map threadInfo; - @Column(name = "user_id") + @Column(name = "user_id", nullable = false) private Long userId; - @Column(name = "platform_id") + @Column(name = "platform_id", nullable = false) private Long platformId; @Column(name = "is_deleted") diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/HostPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/HostPO.java index f0b3054da..5b4131742 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/HostPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/HostPO.java @@ -69,7 +69,7 @@ public class HostPO extends BasePO implements Serializable { @Column(name = "state") private String state; - @Column(name = "cluster_id") + @Column(name = "cluster_id", nullable = false) private Long clusterId; @Transient diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/JobPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/JobPO.java index 30adbb6a6..22938e28e 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/JobPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/JobPO.java @@ -39,14 +39,14 @@ public class JobPO extends BasePO implements Serializable { @Column(name = "id") private Long id; - @Column(name = "state") + @Column(name = "state", nullable = false) private String state; @Column(name = "name") private String name; @Lob - @Column(name = "context") + @Column(name = "context", nullable = false) private String context; @Column(name = "cluster_id") diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/PlatformAuthorizedPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/PlatformAuthorizedPO.java index 595e1f62a..ecd943bcd 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/PlatformAuthorizedPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/PlatformAuthorizedPO.java @@ -39,7 +39,7 @@ public class PlatformAuthorizedPO extends BasePO implements Serializable { @Column(name = "credentials", columnDefinition = "json", nullable = false) private Map credentials; - @Column(name = "platform_id") + @Column(name = "platform_id", nullable = false) private Long platformId; @Column(name = "is_deleted") diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/RepoPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/RepoPO.java index 00030d2c5..53e513ceb 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/RepoPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/RepoPO.java @@ -53,6 +53,6 @@ public class RepoPO extends BasePO implements Serializable { @Column(name = "repo_type") private String repoType; - @Column(name = "cluster_id") + @Column(name = "cluster_id", nullable = false) private Long clusterId; } diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StackPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StackPO.java index 76db3ea9e..5b7add256 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StackPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StackPO.java @@ -35,9 +35,9 @@ public class StackPO extends BasePO implements Serializable { @Column(name = "id") private Long id; - @Column(name = "stack_name") + @Column(name = "stack_name", nullable = false) private String stackName; - @Column(name = "stack_version") + @Column(name = "stack_version", nullable = false) private String stackVersion; } diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StagePO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StagePO.java index 22a2d94c1..dd17195c0 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StagePO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/StagePO.java @@ -37,10 +37,10 @@ public class StagePO extends BasePO implements Serializable { @Column(name = "id") private Long id; - @Column(name = "name") + @Column(name = "name", nullable = false) private String name; - @Column(name = "state") + @Column(name = "state", nullable = false) private String state; @Column(name = "order") @@ -55,7 +55,7 @@ public class StagePO extends BasePO implements Serializable { @Column(name = "context") private String context; - @Column(name = "job_id") + @Column(name = "job_id", nullable = false) private Long jobId; @Column(name = "cluster_id") diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/TaskPO.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/TaskPO.java index 54b507173..7fad46310 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/TaskPO.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/po/TaskPO.java @@ -38,7 +38,7 @@ public class TaskPO extends BasePO implements Serializable { @Column(name = "name") private String name; - @Column(name = "context") + @Column(name = "context", nullable = false) private String context; @Column(name = "state") diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/BaseDao.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/BaseDao.java index 2c85e6f26..686ece108 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/BaseDao.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/BaseDao.java @@ -42,11 +42,36 @@ public interface BaseDao { int save(Entity entity); /** - * Update the entity by primary key. + * Insert all entities. + */ + @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") + @InsertProvider(type = BaseSqlProvider.class, method = "insertList") + int saveAll(List entities); + + /** + * Partially update the entity by primary key. + */ + @UpdateProvider(type = BaseSqlProvider.class, method = "partialUpdateById") + int partialUpdateById(Entity entity); + + /** + * Fully update the entity by primary key. */ @UpdateProvider(type = BaseSqlProvider.class, method = "updateById") int updateById(Entity entity); + /** + * Partially update the entities by primary key. + */ + @UpdateProvider(type = BaseSqlProvider.class, method = "partialUpdateByIds") + int partialUpdateByIds(List entities); + + /** + * Fully update the entities by primary key. + */ + @UpdateProvider(type = BaseSqlProvider.class, method = "updateByIds") + int updateByIds(List entities); + /** * Query the entity by primary key. */ diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/HostDao.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/HostDao.java index 335a5e564..be95624b2 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/HostDao.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/HostDao.java @@ -28,8 +28,6 @@ public interface HostDao extends BaseDao { - int saveAll(@Param("hosts") List hosts); - HostPO findByHostname(@Param("hostname") String hostname); List findAllByHostnameIn(@Param("hostnames") Collection hostnames); diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/RepoDao.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/RepoDao.java index c951dfb35..3c8d30215 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/RepoDao.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/repository/RepoDao.java @@ -30,7 +30,5 @@ public interface RepoDao extends BaseDao { Optional findByRepoName(@Param("repoName") String clusterName); - int saveAll(@Param("clusters") List repos); - List findAllByClusterId(@Param("clusterId") Long clusterId); } diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/BaseSqlProvider.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/BaseSqlProvider.java index 09eaf94db..d2f92968c 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/BaseSqlProvider.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/BaseSqlProvider.java @@ -31,6 +31,7 @@ import java.io.Serializable; import java.lang.reflect.Type; import java.util.Collection; +import java.util.List; @Slf4j public class BaseSqlProvider { @@ -46,6 +47,43 @@ public String insert(Entity entity, ProviderContext context) { return SQLBuilder.insert(tableMetaData, entity, databaseId); } + public String insertList(List entities, ProviderContext context) { + Assert.notNull(entities, "entities must not be null"); + Assert.notEmpty(entities, "entities list must not be empty"); + + String databaseId = context.getDatabaseId(); + + Class entityClass = entities.get(0).getClass(); + + TableMetaData tableMetaData = TableMetaData.forClass(entityClass); + + return SQLBuilder.insertList(tableMetaData, entities, databaseId); + } + + public String partialUpdateById(Entity entity, ProviderContext context) { + Assert.notNull(entity, "entity must not null"); + + String databaseId = context.getDatabaseId(); + + Class entityClass = entity.getClass(); + TableMetaData tableMetaData = TableMetaData.forClass(entityClass); + + return SQLBuilder.update(tableMetaData, entity, databaseId, true); + } + + public String partialUpdateByIds(List entities, ProviderContext context) { + Assert.notNull(entities, "entities must not be null"); + Assert.notEmpty(entities, "entities list must not be empty"); + + String databaseId = context.getDatabaseId(); + + Class entityClass = entities.get(0).getClass(); + + TableMetaData tableMetaData = TableMetaData.forClass(entityClass); + + return SQLBuilder.updateList(tableMetaData, entities, databaseId, true); + } + public String updateById(Entity entity, ProviderContext context) { Assert.notNull(entity, "entity must not null"); @@ -54,7 +92,20 @@ public String updateById(Entity entity, ProviderContext context) { Class entityClass = entity.getClass(); TableMetaData tableMetaData = TableMetaData.forClass(entityClass); - return SQLBuilder.update(tableMetaData, entity, databaseId); + return SQLBuilder.update(tableMetaData, entity, databaseId, false); + } + + public String updateByIds(List entities, ProviderContext context) { + Assert.notNull(entities, "entities must not be null"); + Assert.notEmpty(entities, "entities list must not be empty"); + + String databaseId = context.getDatabaseId(); + + Class entityClass = entities.get(0).getClass(); + + TableMetaData tableMetaData = TableMetaData.forClass(entityClass); + + return SQLBuilder.updateList(tableMetaData, entities, databaseId, false); } public String selectById(Serializable id, ProviderContext context) { diff --git a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/SQLBuilder.java b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/SQLBuilder.java index 08cfdcd72..4321f223b 100644 --- a/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/SQLBuilder.java +++ b/bigtop-manager-dao/src/main/java/org/apache/bigtop/manager/dao/sql/SQLBuilder.java @@ -20,7 +20,11 @@ package org.apache.bigtop.manager.dao.sql; import org.apache.bigtop.manager.common.utils.ClassUtils; +import org.apache.bigtop.manager.dao.annotations.CreateBy; +import org.apache.bigtop.manager.dao.annotations.CreateTime; import org.apache.bigtop.manager.dao.annotations.QueryCondition; +import org.apache.bigtop.manager.dao.annotations.UpdateBy; +import org.apache.bigtop.manager.dao.annotations.UpdateTime; import org.apache.bigtop.manager.dao.enums.DBType; import org.apache.ibatis.jdbc.SQL; @@ -31,10 +35,13 @@ import lombok.extern.slf4j.Slf4j; +import jakarta.persistence.Column; import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -53,7 +60,7 @@ public static String insert(TableMetaData tableMetaData, Entity entity, SQL sql = new SQL(); switch (DBType.toType(databaseId)) { case MYSQL: { - sql.INSERT_INTO(tableMetaData.getTableName()); + sql.INSERT_INTO(keywordsFormat(tableMetaData.getTableName(), DBType.MYSQL)); for (Map.Entry entry : fieldColumnMap.entrySet()) { // Ignore primary key if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { @@ -65,13 +72,13 @@ public static String insert(TableMetaData tableMetaData, Entity entity, } Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); if (!ObjectUtils.isEmpty(value)) { - sql.VALUES("`" + entry.getValue() + "`", getTokenParam(entry.getKey())); + sql.VALUES(keywordsFormat(entry.getValue(), DBType.MYSQL), getTokenParam(entry.getKey())); } } break; } case POSTGRESQL: { - sql.INSERT_INTO("\"" + tableMetaData.getTableName() + "\""); + sql.INSERT_INTO(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); for (Map.Entry entry : fieldColumnMap.entrySet()) { // Ignore primary key if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { @@ -83,7 +90,7 @@ public static String insert(TableMetaData tableMetaData, Entity entity, } Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); if (!ObjectUtils.isEmpty(value)) { - sql.VALUES("\"" + entry.getValue() + "\"", getTokenParam(entry.getKey())); + sql.VALUES(keywordsFormat(entry.getValue(), DBType.POSTGRESQL), getTokenParam(entry.getKey())); } } break; @@ -97,14 +104,106 @@ public static String insert(TableMetaData tableMetaData, Entity entity, return sql.toString(); } - public static String update(TableMetaData tableMetaData, Entity entity, String databaseId) { + public static String insertList(TableMetaData tableMetaData, List entities, String databaseId) { + if (entities == null || entities.isEmpty()) { + throw new IllegalArgumentException("Entities list must not be null or empty"); + } + + Class entityClass = entities.get(0).getClass(); + Map fieldColumnMap = tableMetaData.getFieldColumnMap(); + + SQL sql = new SQL(); + switch (DBType.toType(databaseId)) { + case MYSQL: { + sql.INSERT_INTO(keywordsFormat(tableMetaData.getTableName(), DBType.MYSQL)); + + boolean firstRow = true; + int idx = 0; + for (Entity entity : entities) { + List values = new ArrayList<>(); + for (Map.Entry entry : fieldColumnMap.entrySet()) { + // Ignore primary key + if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { + continue; + } + PropertyDescriptor ps = BeanUtils.getPropertyDescriptor(entityClass, entry.getKey()); + if (ps == null || ps.getReadMethod() == null) { + continue; + } + Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); + if (!ObjectUtils.isEmpty(value)) { + if (firstRow) { + sql.VALUES( + keywordsFormat(entry.getValue(), DBType.MYSQL), + getTokenParam("arg0[" + idx + "]." + entry.getKey())); + } + values.add(getTokenParam("arg0[" + idx + "]." + entry.getKey())); + } + } + if (firstRow) { + firstRow = false; + } else { + sql.ADD_ROW(); + sql.INTO_VALUES(values.toArray(new String[0])); + } + idx++; + } + break; + } + case POSTGRESQL: { + sql.INSERT_INTO(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); + + boolean firstRow = true; + List columns = new ArrayList<>(); + int idx = 0; + for (Entity entity : entities) { + List values = new ArrayList<>(); + for (Map.Entry entry : fieldColumnMap.entrySet()) { + // Ignore primary key + if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { + continue; + } + PropertyDescriptor ps = BeanUtils.getPropertyDescriptor(entityClass, entry.getKey()); + if (ps == null || ps.getReadMethod() == null) { + continue; + } + Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); + if (!ObjectUtils.isEmpty(value)) { + if (firstRow) { + sql.VALUES( + keywordsFormat(entry.getValue(), DBType.POSTGRESQL), + getTokenParam("arg0[" + idx + "]." + entry.getKey())); + } + values.add(getTokenParam("arg0[" + idx + "]." + entry.getKey())); + } + } + if (firstRow) { + firstRow = false; + } else { + sql.ADD_ROW(); + sql.INTO_VALUES(values.toArray(new String[0])); + } + idx++; + } + } + + default: { + log.error("Unsupported data source"); + } + } + + return sql.toString(); + } + + public static String update( + TableMetaData tableMetaData, Entity entity, String databaseId, boolean partial) { Class entityClass = entity.getClass(); Map fieldColumnMap = tableMetaData.getFieldColumnMap(); SQL sql = new SQL(); switch (DBType.toType(databaseId)) { case MYSQL: { - sql.UPDATE(tableMetaData.getTableName()); + sql.UPDATE(keywordsFormat(tableMetaData.getTableName(), DBType.MYSQL)); for (Map.Entry entry : fieldColumnMap.entrySet()) { // Ignore primary key if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { @@ -115,16 +214,25 @@ public static String update(TableMetaData tableMetaData, Entity entity, continue; } Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); - if (!ObjectUtils.isEmpty(value)) { - sql.SET(getEquals(entry.getValue(), entry.getKey())); + if (ObjectUtils.isEmpty(value) && partial) { + continue; } + Field field = ReflectionUtils.findField(entityClass, entry.getKey()); + if (field != null) { + Column column = field.getAnnotation(Column.class); + if (column != null && !column.nullable() && value == null) { + continue; + } + } + sql.SET(getEquals(keywordsFormat(entry.getValue(), DBType.MYSQL), entry.getKey())); } - sql.WHERE(getEquals(tableMetaData.getPkColumn(), tableMetaData.getPkProperty())); + sql.WHERE(getEquals( + keywordsFormat(tableMetaData.getPkColumn(), DBType.MYSQL), tableMetaData.getPkProperty())); break; } case POSTGRESQL: { - sql.UPDATE("\"" + tableMetaData.getTableName() + "\""); + sql.UPDATE(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); for (Map.Entry entry : fieldColumnMap.entrySet()) { // Ignore primary key if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { @@ -135,11 +243,20 @@ public static String update(TableMetaData tableMetaData, Entity entity, continue; } Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); - if (!ObjectUtils.isEmpty(value)) { - sql.SET("\"" + getEquals(entry.getValue() + "\"", entry.getKey())); + if (ObjectUtils.isEmpty(value) && partial) { + continue; + } + Field field = ReflectionUtils.findField(entityClass, entry.getKey()); + if (field != null) { + Column column = field.getAnnotation(Column.class); + if (column != null && !column.nullable() && value == null) { + continue; + } } + sql.SET(getEquals(keywordsFormat(entry.getValue(), DBType.POSTGRESQL), entry.getKey())); } - sql.WHERE(getEquals(tableMetaData.getPkColumn(), tableMetaData.getPkProperty())); + sql.WHERE(getEquals( + keywordsFormat(tableMetaData.getPkColumn(), DBType.POSTGRESQL), tableMetaData.getPkProperty())); break; } default: { @@ -150,6 +267,189 @@ public static String update(TableMetaData tableMetaData, Entity entity, return sql.toString(); } + public static String updateList( + TableMetaData tableMetaData, List entities, String databaseId, boolean partial) { + if (entities == null || entities.isEmpty()) { + throw new IllegalArgumentException("Entities list must not be null or empty"); + } + + Class entityClass = entities.get(0).getClass(); + Map fieldColumnMap = tableMetaData.getFieldColumnMap(); + + StringBuilder sqlBuilder = new StringBuilder(); + switch (DBType.toType(databaseId)) { + case MYSQL: { + sqlBuilder + .append("UPDATE ") + .append(keywordsFormat(tableMetaData.getTableName(), DBType.MYSQL)) + .append(" SET "); + Map setClauses = new LinkedHashMap<>(); + String primaryKey = keywordsFormat("id", DBType.MYSQL); + for (Map.Entry entry : fieldColumnMap.entrySet()) { + // Ignore primary key + if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { + primaryKey = keywordsFormat(entry.getValue(), DBType.MYSQL); + continue; + } + + StringBuilder caseClause = new StringBuilder(); + caseClause + .append(keywordsFormat(entry.getValue(), DBType.MYSQL)) + .append(" = CASE "); + for (Entity entity : entities) { + PropertyDescriptor ps = BeanUtils.getPropertyDescriptor(entityClass, entry.getKey()); + if (ps == null || ps.getReadMethod() == null) { + continue; + } + Field field = ReflectionUtils.findField(entityClass, entry.getKey()); + if (field == null || checkBaseField(field)) { + continue; + } + Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); + PropertyDescriptor pkPs = + BeanUtils.getPropertyDescriptor(entityClass, tableMetaData.getPkProperty()); + if (pkPs == null || pkPs.getReadMethod() == null) { + continue; + } + Object pkValue = ReflectionUtils.invokeMethod(pkPs.getReadMethod(), entity); + + if (!ObjectUtils.isEmpty(value)) { + caseClause + .append("WHEN ") + .append(primaryKey) + .append(" = '") + .append(pkValue) + .append("' THEN '") + .append(escapeSingleQuote(value.toString())) + .append("' "); + } else if (!partial) { + Column column = field.getAnnotation(Column.class); + if (column != null && !column.nullable() && value == null) { + continue; + } + caseClause + .append("WHEN ") + .append(primaryKey) + .append(" = '") + .append(pkValue) + .append("' THEN NULL "); + } + } + caseClause + .append("ELSE ") + .append(keywordsFormat(entry.getValue(), DBType.MYSQL)) + .append(" "); + caseClause.append("END"); + setClauses.put(entry.getValue(), caseClause); + } + sqlBuilder.append(String.join(", ", setClauses.values())); + + sqlBuilder.append(" WHERE ").append(primaryKey).append(" IN ("); + String pkValues = entities.stream() + .map(entity -> { + PropertyDescriptor pkPs = + BeanUtils.getPropertyDescriptor(entityClass, tableMetaData.getPkProperty()); + Object pkValue = ReflectionUtils.invokeMethod(pkPs.getReadMethod(), entity); + return "'" + pkValue.toString() + "'"; + }) + .collect(Collectors.joining(", ")); + + sqlBuilder.append(pkValues).append(")"); + break; + } + case POSTGRESQL: { + sqlBuilder + .append("UPDATE ") + .append("\"") + .append(tableMetaData.getTableName()) + .append("\"") + .append(" SET "); + Map setClauses = new LinkedHashMap<>(); + String primaryKey = keywordsFormat("id", DBType.POSTGRESQL); + for (Map.Entry entry : fieldColumnMap.entrySet()) { + // Ignore primary key + if (Objects.equals(entry.getKey(), tableMetaData.getPkProperty())) { + primaryKey = keywordsFormat(entry.getValue(), DBType.POSTGRESQL); + continue; + } + Field field = ReflectionUtils.findField(entityClass, entry.getKey()); + if (field == null || checkBaseField(field)) { + continue; + } + StringBuilder caseClause = new StringBuilder(); + caseClause + .append(keywordsFormat(entry.getValue(), DBType.POSTGRESQL)) + .append(" = CASE "); + + for (Entity entity : entities) { + PropertyDescriptor ps = BeanUtils.getPropertyDescriptor(entityClass, entry.getKey()); + if (ps == null || ps.getReadMethod() == null) { + continue; + } + Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); + PropertyDescriptor pkPs = + BeanUtils.getPropertyDescriptor(entityClass, tableMetaData.getPkProperty()); + if (pkPs == null || pkPs.getReadMethod() == null) { + continue; + } + Object pkValue = ReflectionUtils.invokeMethod(pkPs.getReadMethod(), entity); + + if (!ObjectUtils.isEmpty(value)) { + caseClause + .append("WHEN ") + .append(primaryKey) + .append(" = '") + .append(pkValue) + .append("' THEN '") + .append(escapeSingleQuote(value.toString())) + .append("' "); + } else if (!partial) { + Column column = field.getAnnotation(Column.class); + if (column != null && !column.nullable() && value == null) { + continue; + } + caseClause + .append("WHEN ") + .append(primaryKey) + .append(" = '") + .append(pkValue) + .append("' THEN NULL "); + } + } + if (caseClause.toString().endsWith("CASE ")) { + caseClause.append("WHEN TRUE THEN "); + } else { + caseClause.append("ELSE "); + } + caseClause + .append(keywordsFormat(entry.getValue(), DBType.POSTGRESQL)) + .append(" "); + caseClause.append("END"); + setClauses.put(entry.getValue(), caseClause); + } + sqlBuilder.append(String.join(", ", setClauses.values())); + + sqlBuilder.append(" WHERE ").append(primaryKey).append(" IN ("); + String pkValues = entities.stream() + .map(entity -> { + PropertyDescriptor pkPs = + BeanUtils.getPropertyDescriptor(entityClass, tableMetaData.getPkProperty()); + Object pkValue = ReflectionUtils.invokeMethod(pkPs.getReadMethod(), entity); + return "'" + pkValue.toString() + "'"; + }) + .collect(Collectors.joining(", ")); + + sqlBuilder.append(pkValues).append(")"); + break; + } + default: { + log.error("Unsupported data source"); + } + } + + return sqlBuilder.toString(); + } + public static String selectById(TableMetaData tableMetaData, String databaseId, Serializable id) { SQL sql = new SQL(); @@ -166,7 +466,7 @@ public static String selectById(TableMetaData tableMetaData, String databaseId, baseColumns = baseColumns.replace("user.", "\"user\"."); } sql.SELECT(baseColumns); - sql.FROM("\"" + tableMetaData.getTableName() + "\""); + sql.FROM(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); sql.WHERE(tableMetaData.getPkColumn() + " = " + id); break; } @@ -207,7 +507,7 @@ public static String selectByIds( baseColumns = baseColumns.replace("user.", "\"user\"."); } sql.SELECT(baseColumns); - sql.FROM("\"" + tableMetaData.getTableName() + "\""); + sql.FROM(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); sql.WHERE(tableMetaData.getPkColumn() + " in (" + idsStr + ")"); break; } @@ -229,7 +529,7 @@ public static String selectAll(TableMetaData tableMetaData, String databaseId) { baseColumns = baseColumns.replace("user.", "\"user\"."); } sql.SELECT(baseColumns); - sql.FROM("\"" + tableMetaData.getTableName() + "\""); + sql.FROM(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); break; case MYSQL: { sql.SELECT(tableMetaData.getBaseColumns()); @@ -253,7 +553,7 @@ public static String deleteById(TableMetaData tableMetaData, String databaseId, break; } case POSTGRESQL: { - sql.FROM("\"" + tableMetaData.getTableName() + "\""); + sql.FROM(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); sql.WHERE(tableMetaData.getPkColumn() + " = " + id); break; } @@ -286,7 +586,7 @@ public static String deleteByIds( } case POSTGRESQL: { String idsStr = ids.stream().map(String::valueOf).collect(Collectors.joining(", ")); - sql.DELETE_FROM("\"" + tableMetaData.getTableName() + "\""); + sql.DELETE_FROM(keywordsFormat(tableMetaData.getTableName(), DBType.POSTGRESQL)); sql.WHERE(tableMetaData.getPkColumn() + " in (" + idsStr + ")"); break; } @@ -318,14 +618,36 @@ public static String findByCondition( return sql.toString(); } + private static String keywordsFormat(String keyword, DBType dbType) { + return switch (dbType) { + case MYSQL -> "`" + keyword + "`"; + case POSTGRESQL -> "\"" + keyword + "\""; + default -> keyword; + }; + } + private static String getEquals(String column, String property) { - return "`" + column + "` = " + getTokenParam(property); + return column + " = " + getTokenParam(property); } private static String getTokenParam(String property) { return "#{" + property + "}"; } + private static String escapeSingleQuote(String input) { + if (input != null) { + return input.replace("'", "''"); + } + return null; + } + + private static boolean checkBaseField(Field field) { + return field.isAnnotationPresent(CreateBy.class) + || field.isAnnotationPresent(CreateTime.class) + || field.isAnnotationPresent(UpdateBy.class) + || field.isAnnotationPresent(UpdateTime.class); + } + private static SQL mysqlCondition(Condition condition, TableMetaData tableMetaData) throws IllegalAccessException { diff --git a/bigtop-manager-dao/src/main/resources/mapper/mysql/HostMapper.xml b/bigtop-manager-dao/src/main/resources/mapper/mysql/HostMapper.xml index 4c475a71d..ea168aff4 100644 --- a/bigtop-manager-dao/src/main/resources/mapper/mysql/HostMapper.xml +++ b/bigtop-manager-dao/src/main/resources/mapper/mysql/HostMapper.xml @@ -100,12 +100,4 @@ - - insert into host (hostname, ipv4, ipv6, os, arch, available_processors, free_memory_size, total_memory_size, free_disk, total_disk, state, cluster_id, create_by, update_by, create_time, update_time) - values - - (#{host.hostname}, #{host.ipv4}, #{host.ipv6}, #{host.os}, #{host.arch}, #{host.availableProcessors}, #{host.freeMemorySize}, #{host.totalMemorySize}, #{host.freeDisk}, #{host.totalDisk}, #{host.state}, #{host.clusterId} ,#{host.createBy},#{host.updateBy},#{host.createTime},#{host.updateTime}) - - - \ No newline at end of file diff --git a/bigtop-manager-dao/src/main/resources/mapper/mysql/RepoMapper.xml b/bigtop-manager-dao/src/main/resources/mapper/mysql/RepoMapper.xml index cee5e8685..d1f0d358d 100644 --- a/bigtop-manager-dao/src/main/resources/mapper/mysql/RepoMapper.xml +++ b/bigtop-manager-dao/src/main/resources/mapper/mysql/RepoMapper.xml @@ -40,14 +40,6 @@ limit 1 - - insert into repo (base_url, os, arch, repo_id, repo_name, repo_type, cluster_id, create_by, update_by, create_time, update_time) - values - - (#{cluster.baseUrl},#{cluster.os},#{cluster.arch},#{cluster.repoId},#{cluster.repoName},#{cluster.repoType},#{cluster.clusterId},#{cluster.createBy},#{cluster.updateBy},#{cluster.createTime},#{cluster.updateTime}) - - - - - insert into host (hostname, ipv4, ipv6, os, arch, available_processors, free_memory_size, total_memory_size, free_disk, total_disk, state, cluster_id, create_by, update_by, create_time, update_time) - values - - (#{host.hostname}, #{host.ipv4}, #{host.ipv6}, #{host.os}, #{host.arch}, #{host.availableProcessors}, #{host.freeMemorySize}, #{host.totalMemorySize}, #{host.freeDisk}, #{host.totalDisk}, #{host.state}, #{host.clusterId} ,#{host.createBy},#{host.updateBy},#{host.createTime},#{host.updateTime}) - - - \ No newline at end of file diff --git a/bigtop-manager-dao/src/main/resources/mapper/postgresql/RepoMapper.xml b/bigtop-manager-dao/src/main/resources/mapper/postgresql/RepoMapper.xml index cee5e8685..d1f0d358d 100644 --- a/bigtop-manager-dao/src/main/resources/mapper/postgresql/RepoMapper.xml +++ b/bigtop-manager-dao/src/main/resources/mapper/postgresql/RepoMapper.xml @@ -40,14 +40,6 @@ limit 1 - - insert into repo (base_url, os, arch, repo_id, repo_name, repo_type, cluster_id, create_by, update_by, create_time, update_time) - values - - (#{cluster.baseUrl},#{cluster.os},#{cluster.arch},#{cluster.repoId},#{cluster.repoName},#{cluster.repoType},#{cluster.clusterId},#{cluster.createBy},#{cluster.updateBy},#{cluster.createTime},#{cluster.updateTime}) - - -