From 7ce7baa2d2207657192b93845969ae200ee89f91 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 27 Apr 2022 23:15:43 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 7 + .../mybatis/core/util/DatabaseUtils.java | 29 +++ .../infra/enums/ErrorCodeConstants.java | 4 + .../yudao-module-infra-biz/pom.xml | 5 + .../admin/db/DataSourceConfigController.java | 73 ++++++++ .../DatabaseDocController.java} | 4 +- .../admin/db/vo/DataSourceConfigBaseVO.java | 27 +++ .../db/vo/DataSourceConfigCreateReqVO.java | 18 ++ .../admin/db/vo/DataSourceConfigRespVO.java | 19 ++ .../db/vo/DataSourceConfigUpdateReqVO.java | 22 +++ .../convert/db/DataSourceConfigConvert.java | 30 ++++ .../dal/dataobject/db/DataSourceConfigDO.java | 38 ++++ .../dal/mysql/db/DataSourceConfigMapper.java | 14 ++ .../service/db/DataSourceConfigService.java | 56 ++++++ .../db/DataSourceConfigServiceImpl.java | 97 ++++++++++ .../db/DataSourceConfigServiceImplTest.java | 119 +++++++++++++ .../src/test/resources/sql/clean.sql | 1 + .../src/test/resources/sql/create_tables.sql | 14 ++ .../yudao-module-member-biz/pom.xml | 2 +- .../src/main/resources/application-dev.yaml | 4 + .../src/main/resources/application-local.yaml | 4 + .../src/main/resources/application.yaml | 1 + .../src/api/infra/dataSourceConfig.js | 43 +++++ .../views/infra/dataSourceConfig/index.vue | 166 ++++++++++++++++++ 24 files changed, 794 insertions(+), 3 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java rename yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/{doc/DbDocController.java => db/DatabaseDocController.java} (98%) create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DataSourceConfigMapper.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java create mode 100755 yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java create mode 100755 yudao-ui-admin/src/api/infra/dataSourceConfig.js create mode 100755 yudao-ui-admin/src/views/infra/dataSourceConfig/index.vue diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 1c871cf32..14a4b1dfc 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -45,6 +45,7 @@ 7.1.0.M6 6.7.0 + 3.0.4 1.18.20 1.4.1.Final 5.6.1 @@ -428,6 +429,12 @@ ${revision} + + com.github.ulisesbocchio + jasypt-spring-boot-starter + ${jasypt-spring-boot-starter.version} + + cn.iocoder.boot yudao-spring-boot-starter-excel diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java new file mode 100644 index 000000000..b282656c5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import java.sql.Connection; +import java.sql.DriverManager; + +/** + * 数据库工具类 + * + * @author 芋道源码 + */ +public class DatabaseUtils { + + /** + * 判断连接是否正确 + * + * @param url 数据源连接 + * @param username 账号 + * @param password 密码 + * @return 是否正确 + */ + public static boolean isConnectionOK(String url, String username, String password) { + try (Connection ignored = DriverManager.getConnection(url, username, password)) { + return true; + } catch (Exception ex) { + return false; + } + } + +} diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index 1528955f9..8dd1a991f 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -49,4 +49,8 @@ public interface ErrorCodeConstants { ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1001006000, "文件配置不存在"); ErrorCode FILE_CONFIG_DELETE_FAIL_MASTER = new ErrorCode(1001006001, "该文件配置不允许删除,原因:它是主配置,删除会导致无法上传文件"); + // ========== 数据源配置 1001007000 ========== + ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1001007000, "数据源配置不存在"); + ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1001007001, "数据源配置不正确,无法进行连接"); + } diff --git a/yudao-module-infra/yudao-module-infra-biz/pom.xml b/yudao-module-infra/yudao-module-infra-biz/pom.xml index 5c4c16d43..cd30fd21e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/pom.xml +++ b/yudao-module-infra/yudao-module-infra-biz/pom.xml @@ -79,6 +79,11 @@ + + com.github.ulisesbocchio + jasypt-spring-boot-starter + + cn.iocoder.boot yudao-spring-boot-starter-excel diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java new file mode 100755 index 000000000..6b535ae98 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Api(tags = "管理后台 - 数据源配置") +@RestController +@RequestMapping("/infra/data-source-config") +@Validated +public class DataSourceConfigController { + + @Resource + private DataSourceConfigService dataSourceConfigService; + + @PostMapping("/create") + @ApiOperation("创建数据源配置") + @PreAuthorize("@ss.hasPermission('infra:data-source-config:create')") + public CommonResult createDataSourceConfig(@Valid @RequestBody DataSourceConfigCreateReqVO createReqVO) { + return success(dataSourceConfigService.createDataSourceConfig(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新数据源配置") + @PreAuthorize("@ss.hasPermission('infra:data-source-config:update')") + public CommonResult updateDataSourceConfig(@Valid @RequestBody DataSourceConfigUpdateReqVO updateReqVO) { + dataSourceConfigService.updateDataSourceConfig(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @ApiOperation("删除数据源配置") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('infra:data-source-config:delete')") + public CommonResult deleteDataSourceConfig(@RequestParam("id") Long id) { + dataSourceConfigService.deleteDataSourceConfig(id); + return success(true); + } + + @GetMapping("/get") + @ApiOperation("获得数据源配置") + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('infra:data-source-config:query')") + public CommonResult getDataSourceConfig(@RequestParam("id") Long id) { + DataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id); + return success(DataSourceConfigConvert.INSTANCE.convert(dataSourceConfig)); + } + + @GetMapping("/list") + @ApiOperation("获得数据源配置列表") + @PreAuthorize("@ss.hasPermission('infra:data-source-config:query')") + public CommonResult> getDataSourceConfigList() { + List list = dataSourceConfigService.getDataSourceConfigList(); + return success(DataSourceConfigConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java similarity index 98% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java index 83d9db798..eb35d4555 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/doc/DbDocController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.infra.controller.admin.doc; +package cn.iocoder.yudao.module.infra.controller.admin.db; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; @@ -30,7 +30,7 @@ import java.util.Arrays; @Api(tags = "管理后台 - 数据库文档") @RestController @RequestMapping("/infra/db-doc") -public class DbDocController { +public class DatabaseDocController { @Resource private DynamicDataSourceProperties dynamicDataSourceProperties; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java new file mode 100755 index 000000000..ae3d97dce --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +/** +* 数据源配置 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class DataSourceConfigBaseVO { + + @ApiModelProperty(value = "参数名称", required = true, example = "test") + @NotNull(message = "参数名称不能为空") + private String name; + + @ApiModelProperty(value = "数据源连接", required = true, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro") + @NotNull(message = "数据源连接不能为空") + private String url; + + @ApiModelProperty(value = "用户名", required = true, example = "root") + @NotNull(message = "用户名不能为空") + private String username; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java new file mode 100755 index 000000000..13085f9b1 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +@ApiModel("管理后台 - 数据源配置创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DataSourceConfigCreateReqVO extends DataSourceConfigBaseVO { + + @ApiModelProperty(value = "密码", required = true, example = "123456") + @NotNull(message = "密码不能为空") + private String password; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java new file mode 100755 index 000000000..af63aa0dd --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; + +@ApiModel("管理后台 - 数据源配置 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DataSourceConfigRespVO extends DataSourceConfigBaseVO { + + @ApiModelProperty(value = "主键编号", required = true, example = "1024") + private Integer id; + + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java new file mode 100755 index 000000000..134f3e9df --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.infra.controller.admin.db.vo; + +import lombok.*; +import java.util.*; +import io.swagger.annotations.*; +import javax.validation.constraints.*; + +@ApiModel("管理后台 - 数据源配置更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DataSourceConfigUpdateReqVO extends DataSourceConfigBaseVO { + + @ApiModelProperty(value = "主键编号", required = true, example = "1024") + @NotNull(message = "主键编号不能为空") + private Long id; + + @ApiModelProperty(value = "密码", required = true, example = "123456") + @NotNull(message = "密码不能为空") + private String password; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java new file mode 100755 index 000000000..d81d85cee --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.convert.db; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; + +/** + * 数据源配置 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface DataSourceConfigConvert { + + DataSourceConfigConvert INSTANCE = Mappers.getMapper(DataSourceConfigConvert.class); + + DataSourceConfigDO convert(DataSourceConfigCreateReqVO bean); + + DataSourceConfigDO convert(DataSourceConfigUpdateReqVO bean); + + DataSourceConfigRespVO convert(DataSourceConfigDO bean); + + List convertList(List list); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java new file mode 100644 index 000000000..6508d1d18 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.db; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * 数据源配置 + * + * @author 芋道源码 + */ +@TableName("infra_data_source_config") +@Data +public class DataSourceConfigDO extends BaseDO { + + /** + * 主键编号 + */ + private Long id; + /** + * 连接名 + */ + private String name; + + /** + * 数据源连接 + */ + private String url; + /** + * 用户名 + */ + private String username; + /** + * 密码 + */ + private String password; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DataSourceConfigMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DataSourceConfigMapper.java new file mode 100755 index 000000000..5ad8be428 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DataSourceConfigMapper.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.db; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 数据源配置 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface DataSourceConfigMapper extends BaseMapperX { +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java new file mode 100755 index 000000000..b5e9e21ee --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import org.w3c.dom.stylesheets.LinkStyle; + +import javax.validation.Valid; +import java.util.List; + +/** + * 数据源配置 Service 接口 + * + * @author 芋道源码 + */ +public interface DataSourceConfigService { + + /** + * 创建数据源配置 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createDataSourceConfig(@Valid DataSourceConfigCreateReqVO createReqVO); + + /** + * 更新数据源配置 + * + * @param updateReqVO 更新信息 + */ + void updateDataSourceConfig(@Valid DataSourceConfigUpdateReqVO updateReqVO); + + /** + * 删除数据源配置 + * + * @param id 编号 + */ + void deleteDataSourceConfig(Long id); + + /** + * 获得数据源配置 + * + * @param id 编号 + * @return 数据源配置 + */ + DataSourceConfigDO getDataSourceConfig(Long id); + + /** + * 获得数据源配置列表 + * + * @return 数据源配置列表 + */ + List getDataSourceConfigList(); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java new file mode 100755 index 000000000..e2f1a6559 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.hutool.db.DbUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; +import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; +import org.jasypt.encryption.StringEncryptor; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import java.sql.Connection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_OK; + +/** + * 数据源配置 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class DataSourceConfigServiceImpl implements DataSourceConfigService { + + @Resource + private DataSourceConfigMapper dataSourceConfigMapper; + + @Resource + private StringEncryptor stringEncryptor; + + @Override + public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) { + DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO); + checkConnectionOK(dataSourceConfig); + + // 插入 + dataSourceConfig.setPassword(stringEncryptor.encrypt(createReqVO.getPassword())); + dataSourceConfigMapper.insert(dataSourceConfig); + // 返回 + return dataSourceConfig.getId(); + } + + @Override + public void updateDataSourceConfig(DataSourceConfigUpdateReqVO updateReqVO) { + // 校验存在 + validateDataSourceConfigExists(updateReqVO.getId()); + DataSourceConfigDO updateObj = DataSourceConfigConvert.INSTANCE.convert(updateReqVO); + checkConnectionOK(updateObj); + + // 更新 + updateObj.setPassword(stringEncryptor.encrypt(updateObj.getPassword())); + dataSourceConfigMapper.updateById(updateObj); + } + + @Override + public void deleteDataSourceConfig(Long id) { + // 校验存在 + validateDataSourceConfigExists(id); + // 删除 + dataSourceConfigMapper.deleteById(id); + } + + private void validateDataSourceConfigExists(Long id) { + if (dataSourceConfigMapper.selectById(id) == null) { + throw exception(DATA_SOURCE_CONFIG_NOT_EXISTS); + } + } + + @Override + public DataSourceConfigDO getDataSourceConfig(Long id) { + DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id); + dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword())); + return dataSourceConfig; + } + + @Override + public List getDataSourceConfigList() { + return dataSourceConfigMapper.selectList(); + } + + private void checkConnectionOK(DataSourceConfigDO config) { + boolean success = DatabaseUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword()); + if (!success) { + throw exception(DATA_SOURCE_CONFIG_NOT_OK); + } + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java new file mode 100755 index 000000000..5c51b198e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; +import org.jasypt.encryption.StringEncryptor; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link DataSourceConfigServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(DataSourceConfigServiceImpl.class) +public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { + + @Resource + private DataSourceConfigServiceImpl dataSourceConfigService; + + @Resource + private DataSourceConfigMapper dataSourceConfigMapper; + + @MockBean + private StringEncryptor stringEncryptor; + + @Test + public void testCreateDataSourceConfig_success() { + try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + // 准备参数 + DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class); + // mock 方法 + when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); + databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); + + // 调用 + Long dataSourceConfigId = dataSourceConfigService.createDataSourceConfig(reqVO); + // 断言 + assertNotNull(dataSourceConfigId); + // 校验记录的属性是否正确 + DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(dataSourceConfigId); + assertPojoEquals(reqVO, dataSourceConfig, "password"); + assertEquals("123456", dataSourceConfig.getPassword()); + } + } + + @Test + public void testUpdateDataSourceConfig_success() { + try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + // mock 数据 + DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); + dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 + // 准备参数 + DataSourceConfigUpdateReqVO reqVO = randomPojo(DataSourceConfigUpdateReqVO.class, o -> { + o.setId(dbDataSourceConfig.getId()); // 设置更新的 ID + }); + // mock 方法 + when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); + databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); + + // 调用 + dataSourceConfigService.updateDataSourceConfig(reqVO); + // 校验是否更新正确 + DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, dataSourceConfig, "password"); + assertEquals("123456", dataSourceConfig.getPassword()); + } + } + + @Test + public void testUpdateDataSourceConfig_notExists() { + // 准备参数 + DataSourceConfigUpdateReqVO reqVO = randomPojo(DataSourceConfigUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> dataSourceConfigService.updateDataSourceConfig(reqVO), DATA_SOURCE_CONFIG_NOT_EXISTS); + } + + @Test + public void testDeleteDataSourceConfig_success() { + // mock 数据 + DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); + dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbDataSourceConfig.getId(); + + // 调用 + dataSourceConfigService.deleteDataSourceConfig(id); + // 校验数据不存在了 + assertNull(dataSourceConfigMapper.selectById(id)); + } + + @Test + public void testDeleteDataSourceConfig_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> dataSourceConfigService.deleteDataSourceConfig(id), DATA_SOURCE_CONFIG_NOT_EXISTS); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql index cc8316837..eb05d3d5a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/clean.sql @@ -9,3 +9,4 @@ DELETE FROM "infra_file"; DELETE FROM "infra_api_error_log"; DELETE FROM "infra_test_demo"; DELETE FROM "infra_file_config"; +DELETE FROM "infra_data_source_config"; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql index 3c86102e6..53d8594fe 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/sql/create_tables.sql @@ -168,3 +168,17 @@ CREATE TABLE IF NOT EXISTS "infra_test_demo" ( "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '字典类型表'; + +CREATE TABLE IF NOT EXISTS "infra_data_source_config" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar(100) NOT NULL, + "url" varchar(1024) NOT NULL, + "username" varchar(255) NOT NULL, + "password" varchar(255) NOT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '数据源配置表'; diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml index f1b48a819..11780b8a0 100644 --- a/yudao-module-member/yudao-module-member-biz/pom.xml +++ b/yudao-module-member/yudao-module-member-biz/pom.xml @@ -77,8 +77,8 @@ yudao-spring-boot-starter-test test - + diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 256c5beb8..0c11d2f1b 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -61,6 +61,10 @@ spring: port: 6379 # 端口 database: 1 # 数据库索引 +jasypt: + encryptor: + password: yuanma # 加解密的秘钥 + --- #################### 定时任务相关配置 #################### # Quartz 配置项,对应 QuartzProperties 配置类 diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 0d5f777d0..d8ce9deee 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -61,6 +61,10 @@ spring: port: 6379 # 端口 database: 0 # 数据库索引 +jasypt: + encryptor: + password: yuanma # 加解密的秘钥 + --- #################### 定时任务相关配置 #################### # Quartz 配置项,对应 QuartzProperties 配置类 diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 76d5e0454..247af4d03 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -123,6 +123,7 @@ yudao: - infra_job - infra_job_log - infra_job_log + - infra_data_source_config sms-code: # 短信验证码相关的配置项 expire-times: 10m send-frequency: 1m diff --git a/yudao-ui-admin/src/api/infra/dataSourceConfig.js b/yudao-ui-admin/src/api/infra/dataSourceConfig.js new file mode 100755 index 000000000..2d96b49cc --- /dev/null +++ b/yudao-ui-admin/src/api/infra/dataSourceConfig.js @@ -0,0 +1,43 @@ +import request from '@/utils/request' + +// 创建数据源配置 +export function createDataSourceConfig(data) { + return request({ + url: '/infra/data-source-config/create', + method: 'post', + data: data + }) +} + +// 更新数据源配置 +export function updateDataSourceConfig(data) { + return request({ + url: '/infra/data-source-config/update', + method: 'put', + data: data + }) +} + +// 删除数据源配置 +export function deleteDataSourceConfig(id) { + return request({ + url: '/infra/data-source-config/delete?id=' + id, + method: 'delete' + }) +} + +// 获得数据源配置 +export function getDataSourceConfig(id) { + return request({ + url: '/infra/data-source-config/get?id=' + id, + method: 'get' + }) +} + +// 获得数据源配置列表 +export function getDataSourceConfigList() { + return request({ + url: '/infra/data-source-config/list', + method: 'get', + }) +} diff --git a/yudao-ui-admin/src/views/infra/dataSourceConfig/index.vue b/yudao-ui-admin/src/views/infra/dataSourceConfig/index.vue new file mode 100755 index 000000000..ddd2800a2 --- /dev/null +++ b/yudao-ui-admin/src/views/infra/dataSourceConfig/index.vue @@ -0,0 +1,166 @@ + + + From d04271b965f71dc75f10ea7b0e32692d7981ea5f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 27 Apr 2022 23:26:03 +0800 Subject: [PATCH 02/23] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E7=AE=A1=E7=90=86=20SQL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/ruoyi-vue-pro.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql index 2fbf683a5..080f33e6f 100644 --- a/sql/ruoyi-vue-pro.sql +++ b/sql/ruoyi-vue-pro.sql @@ -4824,4 +4824,18 @@ INSERT INTO `system_user_session` VALUES ('fe11c39cfc2740a992063bf05bd170f3', 1, INSERT INTO `system_user_session` VALUES ('ffe28d833fea4e76a0b2b6bcde9236c2', 1, 2, '2022-04-03 22:03:16', 'admin', '0:0:0:0:0:0:0:1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36', NULL, '2022-04-02 22:03:16', NULL, '2022-04-03 14:21:23', b'1', 1); COMMIT; +CREATE TABLE `infra_data_source_config` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '参数名称', + `url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '数据源连接', + `username` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '密码', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='数据源配置表'; + SET FOREIGN_KEY_CHECKS = 1; From d79549b48a635c856f8b8c26b1d2155f56163096 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 28 Apr 2022 19:27:59 +0800 Subject: [PATCH 03/23] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=99=A8=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20DatabaseTableDAO=20=E6=8A=BD=E8=B1=A1=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=20db=20=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/core/util/DatabaseUtils.java | 29 ------- .../mybatis/core/util/JdbcUtils.java | 85 +++++++++++++++++++ .../admin/codegen/CodegenController.java | 4 +- .../infra/convert/codegen/CodegenConvert.java | 12 +-- .../dataobject/codegen/CodegenColumnDO.java | 1 - .../dal/dataobject/db/DataSourceConfigDO.java | 5 ++ .../DatabaseColumnDO.java} | 8 +- .../DatabaseTableDO.java} | 10 +-- .../dal/mysql/codegen/SchemaColumnMapper.java | 19 ----- .../dal/mysql/codegen/SchemaTableMapper.java | 26 ------ .../infra/dal/mysql/db/DatabaseTableDAO.java | 57 +++++++++++++ .../mysql/db/DatabaseTableMySQLDAOImpl.java | 70 +++++++++++++++ .../infra/service/codegen/CodegenService.java | 4 +- .../service/codegen/CodegenServiceImpl.java | 39 ++++----- .../service/codegen/inner/CodegenBuilder.java | 12 +-- .../codegen/inner/CodegenSQLParser.java | 30 +++---- .../service/db/DataSourceConfigService.java | 3 +- .../db/DataSourceConfigServiceImpl.java | 33 +++++-- .../service/db/DatabaseTableService.java | 43 ++++++++++ .../service/db/DatabaseTableServiceImpl.java | 74 ++++++++++++++++ .../db/DataSourceConfigServiceImplTest.java | 10 +-- 21 files changed, 419 insertions(+), 155 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java rename yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/{codegen/SchemaColumnDO.java => db/DatabaseColumnDO.java} (67%) rename yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/{codegen/SchemaTableDO.java => db/DatabaseTableDO.java} (56%) delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java deleted file mode 100644 index b282656c5..000000000 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/DatabaseUtils.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.framework.mybatis.core.util; - -import java.sql.Connection; -import java.sql.DriverManager; - -/** - * 数据库工具类 - * - * @author 芋道源码 - */ -public class DatabaseUtils { - - /** - * 判断连接是否正确 - * - * @param url 数据源连接 - * @param username 账号 - * @param password 密码 - * @return 是否正确 - */ - public static boolean isConnectionOK(String url, String username, String password) { - try (Connection ignored = DriverManager.getConnection(url, username, password)) { - return true; - } catch (Exception ex) { - return false; - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java new file mode 100644 index 000000000..f3e875e3c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/JdbcUtils.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import com.baomidou.mybatisplus.annotation.DbType; +import lombok.SneakyThrows; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * JDBC 工具类 + * + * @author 芋道源码 + */ +public class JdbcUtils { + + /** + * 判断连接是否正确 + * + * @param url 数据源连接 + * @param username 账号 + * @param password 密码 + * @return 是否正确 + */ + public static boolean isConnectionOK(String url, String username, String password) { + try (Connection ignored = DriverManager.getConnection(url, username, password)) { + return true; + } catch (Exception ex) { + return false; + } + } + + /** + * 获得连接 + * + * @param url 数据源连接 + * @param username 账号 + * @param password 密码 + * @return 是否正确 + */ + @SneakyThrows + public static Connection getConnection(String url, String username, String password) { + return DriverManager.getConnection(url, username, password); + } + + /** + * 执行指定 SQL,返回查询列表 + * + * 参考 {@link JdbcTemplate#query(String, RowMapper)} 实现,主要考虑 JdbcTemplate 不支持使用指定 Connection 查询 + * + * @param connection 数据库连接 + * @param sql SQL + * @param handler 行处理器 + * @return 列表 + */ + @SneakyThrows + public static List query(Connection connection, String sql, RowMapper handler) { + try (PreparedStatement ps = connection.prepareStatement(sql); + ResultSet rs = ps.executeQuery()) { + // 处理结果 + List result = new ArrayList<>(); + int rowNum = 0; + while (rs.next()) { + result.add(handler.mapRow(rs, rowNum++)); + } + return result; + } + } + + /** + * 获得 URL 对应的 DB 类型 + * + * @param url URL + * @return DB 类型 + */ + public static DbType getDbType(String url) { + String name = com.alibaba.druid.util.JdbcUtils.getDbType(url, null); + return DbType.getDbType(name); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java index 9b6b87048..40bd69271 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java @@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTab import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import cn.iocoder.yudao.module.infra.service.codegen.CodegenService; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; @@ -58,7 +58,7 @@ public class CodegenController { @RequestParam(value = "tableName", required = false) String tableName, @RequestParam(value = "tableComment", required = false) String tableComment) { // 获得数据库自带的表定义列表 - List schemaTables = codegenService.getSchemaTableList(tableName, tableComment); + List schemaTables = codegenService.getSchemaTableList(tableName, tableComment); // 移除在 Codegen 中,已经存在的 Set existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName); schemaTables.removeIf(table -> existsTables.contains(table.getTableName())); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java index 9f5d8583f..ce14ce40c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java @@ -9,8 +9,8 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTa import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.SchemaTableRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -25,11 +25,11 @@ public interface CodegenConvert { // ========== InformationSchemaTableDO 和 InformationSchemaColumnDO 相关 ========== - CodegenTableDO convert(SchemaTableDO bean); + CodegenTableDO convert(DatabaseTableDO bean); - List convertList(List list); + List convertList(List list); - CodegenTableRespVO convert(SchemaColumnDO bean); + CodegenTableRespVO convert(DatabaseColumnDO bean); // ========== CodegenTableDO 相关 ========== @@ -47,7 +47,7 @@ public interface CodegenConvert { List convertList03(List columns); - List convertList04(List list); + List convertList04(List list); // ========== 其它 ========== diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java index 355b0f9e6..518552255 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenColumnDO.java @@ -74,7 +74,6 @@ public class CodegenColumnDO extends BaseDO { /** * Java 属性名 */ -// @NotBlank(message = "Java属性不能为空") private String javaField; /** * 字典类型 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java index 6508d1d18..a8450831a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DataSourceConfigDO.java @@ -13,6 +13,11 @@ import lombok.Data; @Data public class DataSourceConfigDO extends BaseDO { + /** + * 主键编号 - Master 数据源 + */ + public static final Long ID_MASTER = 0L; + /** * 主键编号 */ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java similarity index 67% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java index 0d7cd6cbd..f8f62151f 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaColumnDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseColumnDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.infra.dal.dataobject.codegen; +package cn.iocoder.yudao.module.infra.dal.dataobject.db; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @@ -10,10 +10,9 @@ import lombok.Data; * * @author 芋道源码 */ -@TableName(value = "information_schema.columns", autoResultMap = true) @Data @Builder -public class SchemaColumnDO { +public class DatabaseColumnDO { /** * 表名称 @@ -34,17 +33,14 @@ public class SchemaColumnDO { /** * 是否允许为空 */ - @TableField("case when is_nullable = 'yes' then '1' else '0' end") private Boolean nullable; /** * 是否主键 */ - @TableField("case when column_key = 'PRI' then '1' else '0' end") private Boolean primaryKey; /** * 是否自增 */ - @TableField("case when extra = 'auto_increment' then '1' else '0' end") private Boolean autoIncrement; /** * 排序字段 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java similarity index 56% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java index a70753e1a..90ea8529a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/SchemaTableDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/db/DatabaseTableDO.java @@ -1,6 +1,5 @@ -package cn.iocoder.yudao.module.infra.dal.dataobject.codegen; +package cn.iocoder.yudao.module.infra.dal.dataobject.db; -import com.baomidou.mybatisplus.annotation.TableName; import lombok.Builder; import lombok.Data; @@ -11,15 +10,10 @@ import java.util.Date; * * @author 芋道源码 */ -@TableName(value = "information_schema.tables", autoResultMap = true) @Data @Builder -public class SchemaTableDO { +public class DatabaseTableDO { - /** - * 数据库 - */ - private String tableSchema; /** * 表名称 */ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java deleted file mode 100644 index b31d4aede..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaColumnMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.infra.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -@Mapper -public interface SchemaColumnMapper extends BaseMapperX { - - default List selectListByTableName(String tableSchema, String tableName) { - return selectList(new QueryWrapper().eq("table_name", tableName) - .eq("table_schema", tableSchema) - .orderByAsc("ordinal_position")); - } - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java deleted file mode 100644 index 050e48fbd..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/SchemaTableMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.infra.dal.mysql.codegen; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -@Mapper -public interface SchemaTableMapper extends BaseMapperX { - - default List selectList(Collection tableSchemas, String tableName, String tableComment) { - return selectList(new QueryWrapperX().in("table_schema", tableSchemas) - .likeIfPresent("table_name", tableName) - .likeIfPresent("table_comment", tableComment)); - } - - default SchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) { - return selectOne(new QueryWrapper().eq("table_schema",tableSchema) - .eq("table_name", tableName)); - } - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java new file mode 100644 index 000000000..cfc99a653 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableDAO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.db; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; +import com.baomidou.mybatisplus.annotation.DbType; + +import java.sql.Connection; +import java.util.List; + +/** + * 数据库 Table DAO 接口 + * + * @author 芋道源码 + */ +public interface DatabaseTableDAO { + + /** + * 获得表列表,基于表名称 + 表描述进行模糊匹配 + * + * @param connection 数据库连接 + * @param tableNameLike 表名称,模糊匹配 + * @param tableCommentLike 表描述,模糊匹配 + * @return 表列表 + */ + List selectTableList(Connection connection, String tableNameLike, String tableCommentLike); + + /** + * 获得指定表名 + * + * @param connection 数据库连接 + * @param tableName 表名称 + * @return 表 + */ + default DatabaseTableDO selectTable(Connection connection, String tableName) { + // 考虑到对性能没有要求,直接查询列表,然后内存过滤到记录 + List tables = selectTableList(connection, tableName, null); + return CollUtil.findOne(tables, table -> table.getTableName().equalsIgnoreCase(tableName)); + } + + /** + * 获得指定表的字段列表 + * + * @param connection 数据库连接 + * @param tableName 表名称 + * @return 字段列表 + */ + List selectColumnList(Connection connection, String tableName); + + /** + * 获得数据库的类型 + * + * @return 数据库的类型 + */ + DbType getType(); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java new file mode 100644 index 000000000..c9d933d96 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/db/DatabaseTableMySQLDAOImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.db; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; +import com.baomidou.mybatisplus.annotation.DbType; +import org.springframework.stereotype.Repository; + +import java.sql.Connection; +import java.util.List; + +/** + * {@link DatabaseTableDAO} 的 MySQL 实现类 + * + * @author 芋道源码 + */ +@Repository +public class DatabaseTableMySQLDAOImpl implements DatabaseTableDAO { + + @Override + public List selectTableList(Connection connection, String tableNameLike, String tableCommentLike) { + // 拼接 SQL + String sql = "SELECT table_name, table_comment, create_time" + + " FROM information_schema.TABLES" + + " WHERE table_schema = (SELECT DATABASE())"; + if (StrUtil.isNotEmpty(tableNameLike)) { + sql += StrUtil.format(" AND table_name LIKE '%{}%'", tableNameLike); + } + if (StrUtil.isNotEmpty(tableCommentLike)) { + sql += StrUtil.format(" AND table_comment LIKE '%{}%'", tableCommentLike); + } + // 执行并返回结果 + return JdbcUtils.query(connection, sql, (rs, rowNum) -> DatabaseTableDO.builder() + .tableName(rs.getString("table_name")) + .tableComment(rs.getString("table_comment")) + .createTime(rs.getDate("create_time")) + .build()); + } + + @Override + public List selectColumnList(Connection connection, String tableName) { + // 拼接 SQL + String sql = "SELECT table_name, column_name, column_type, column_comment, " + + " (CASE WHEN is_nullable = 'yes' THEN '1' ELSE '0' END) AS nullable," + + " (CASE WHEN column_key = 'PRI' THEN '1' ELSE '0' END) AS primary_key," + + " (CASE WHEN extra = 'auto_increment' THEN '1' ELSE '0' END) AS auto_increment," + + " ordinal_position" + + " FROM information_schema.COLUMNS" + + " WHERE table_schema = (SELECT DATABASE())" + + String.format(" AND table_name = '%s'", tableName); + // 执行并返回结果 + return JdbcUtils.query(connection, sql, (rs, rowNum) -> DatabaseColumnDO.builder() + .tableName(rs.getString("table_name")) + .columnName(rs.getString("column_name")) + .columnType(rs.getString("column_type")) + .columnComment(rs.getString("column_comment")) + .nullable(rs.getBoolean("nullable")) + .primaryKey(rs.getBoolean("primary_key")) + .autoIncrement(rs.getBoolean("auto_increment")) + .ordinalPosition(rs.getInt("ordinal_position")) + .build()); + } + + @Override + public DbType getType() { + return DbType.MYSQL; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java index c774c88c9..7d3951afa 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateRe import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import java.util.List; import java.util.Map; @@ -119,6 +119,6 @@ public interface CodegenService { * @param tableComment 表描述 * @return 表定义列表 */ - List getSchemaTableList(String tableName, String tableComment); + List getSchemaTableList(String tableName, String tableComment); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java index cdf5d3dc7..cdeda9d67 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java @@ -8,17 +8,16 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTa import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper; -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaColumnMapper; -import cn.iocoder.yudao.module.infra.dal.mysql.codegen.SchemaTableMapper; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenImportTypeEnum; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenSQLParser; +import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import org.apache.commons.collections4.KeyValue; import org.springframework.stereotype.Service; @@ -43,9 +42,8 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; public class CodegenServiceImpl implements CodegenService { @Resource - private SchemaTableMapper schemaTableMapper; - @Resource - private SchemaColumnMapper schemaColumnMapper; + private DatabaseTableService databaseTableService; + @Resource private CodegenTableMapper codegenTableMapper; @Resource @@ -63,7 +61,7 @@ public class CodegenServiceImpl implements CodegenService { private CodegenProperties codegenProperties; private Long createCodegen0(Long userId, CodegenImportTypeEnum importType, - SchemaTableDO schemaTable, List schemaColumns) { + DatabaseTableDO schemaTable, List schemaColumns) { // 校验导入的表和字段非空 if (schemaTable == null) { throw exception(CODEGEN_IMPORT_TABLE_NULL); @@ -90,10 +88,10 @@ public class CodegenServiceImpl implements CodegenService { @Override public Long createCodegenListFromSQL(Long userId, String sql) { // 从 SQL 中,获得数据库表结构 - SchemaTableDO schemaTable; - List schemaColumns; + DatabaseTableDO schemaTable; + List schemaColumns; try { - KeyValue> result = CodegenSQLParser.parse(sql); + KeyValue> result = CodegenSQLParser.parse(sql); schemaTable = result.getKey(); schemaColumns = result.getValue(); } catch (Exception ex) { @@ -108,8 +106,8 @@ public class CodegenServiceImpl implements CodegenService { // 获取当前schema String tableSchema = codegenProperties.getDbSchemas().iterator().next(); // 从数据库中,获得数据库表结构 - SchemaTableDO schemaTable = schemaTableMapper.selectByTableSchemaAndTableName(tableSchema, tableName); - List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName); + DatabaseTableDO schemaTable = databaseTableService.getTable(0L, tableName); + List schemaColumns = databaseTableService.getColumnList(0L, tableName); // 导入 return this.createCodegen0(userId, CodegenImportTypeEnum.DB, schemaTable, schemaColumns); } @@ -147,9 +145,8 @@ public class CodegenServiceImpl implements CodegenService { if (table == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } - String tableSchema = codegenProperties.getDbSchemas().iterator().next(); // 从数据库中,获得数据库表结构 - List schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, table.getTableName()); + List schemaColumns = databaseTableService.getColumnList(0L, table.getTableName()); // 执行同步 this.syncCodegen0(tableId, schemaColumns); @@ -164,9 +161,9 @@ public class CodegenServiceImpl implements CodegenService { throw exception(CODEGEN_TABLE_NOT_EXISTS); } // 从 SQL 中,获得数据库表结构 - List schemaColumns; + List schemaColumns; try { - KeyValue> result = CodegenSQLParser.parse(sql); + KeyValue> result = CodegenSQLParser.parse(sql); schemaColumns = result.getValue(); } catch (Exception ex) { throw exception(CODEGEN_PARSE_SQL_ERROR); @@ -176,12 +173,12 @@ public class CodegenServiceImpl implements CodegenService { this.syncCodegen0(tableId, schemaColumns); } - private void syncCodegen0(Long tableId, List schemaColumns) { + private void syncCodegen0(Long tableId, List schemaColumns) { // 校验导入的字段不为空 if (CollUtil.isEmpty(schemaColumns)) { throw exception(CODEGEN_SYNC_COLUMNS_NULL); } - Set schemaColumnNames = CollectionUtils.convertSet(schemaColumns, SchemaColumnDO::getColumnName); + Set schemaColumnNames = CollectionUtils.convertSet(schemaColumns, DatabaseColumnDO::getColumnName); // 构建 CodegenColumnDO 数组,只同步新增的字段 List codegenColumns = codegenColumnMapper.selectListByTableId(tableId); @@ -255,8 +252,8 @@ public class CodegenServiceImpl implements CodegenService { } @Override - public List getSchemaTableList(String tableName, String tableComment) { - List tables = schemaTableMapper.selectList(codegenProperties.getDbSchemas(), tableName, tableComment); + public List getSchemaTableList(String tableName, String tableComment) { + List tables = databaseTableService.getTableList(0L, tableName, tableComment); // TODO 强制移除 Quartz 的表,未来做成可配置 tables.removeIf(table -> table.getTableName().startsWith("QRTZ_")); tables.removeIf(table -> table.getTableName().startsWith("ACT_")); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java index fe07df7a7..17ebbf9fe 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java @@ -7,8 +7,8 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnHtmlTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenColumnListConditionEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; @@ -22,8 +22,8 @@ import static cn.hutool.core.text.CharSequenceUtil.*; /** * 代码生成器的 Builder,负责: - * 1. 将数据库的表 {@link SchemaTableDO} 定义,构建成 {@link CodegenTableDO} - * 2. 将数据库的列 {@link SchemaColumnDO} 构定义,建成 {@link CodegenColumnDO} + * 1. 将数据库的表 {@link DatabaseTableDO} 定义,构建成 {@link CodegenTableDO} + * 2. 将数据库的列 {@link DatabaseColumnDO} 构定义,建成 {@link CodegenColumnDO} */ @Component public class CodegenBuilder { @@ -109,7 +109,7 @@ public class CodegenBuilder { LIST_OPERATION_RESULT_EXCLUDE_COLUMN.remove("createTime"); // 创建时间,还是需要返回的 } - public CodegenTableDO buildTable(SchemaTableDO schemaTable) { + public CodegenTableDO buildTable(DatabaseTableDO schemaTable) { CodegenTableDO table = CodegenConvert.INSTANCE.convert(schemaTable); initTableDefault(table); return table; @@ -133,7 +133,7 @@ public class CodegenBuilder { table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType()); } - public List buildColumns(Long tableId, List schemaColumns) { + public List buildColumns(Long tableId, List schemaColumns) { List columns = CodegenConvert.INSTANCE.convertList(schemaColumns); for (CodegenColumnDO column : columns) { column.setTableId(tableId); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java index 016a1dbc5..0438cda25 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenSQLParser.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaColumnDO; -import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.SchemaTableDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import com.alibaba.druid.DbType; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -21,7 +21,7 @@ import java.util.Objects; import static com.alibaba.druid.sql.SQLUtils.normalize; /** - * SQL 解析器,将创建表的 SQL,解析成 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象, + * SQL 解析器,将创建表的 SQL,解析成 {@link DatabaseTableDO} 和 {@link DatabaseColumnDO} 对象, * 后续可以基于它们,生成代码~ * * @author 芋道源码 @@ -29,18 +29,18 @@ import static com.alibaba.druid.sql.SQLUtils.normalize; public class CodegenSQLParser { /** - * 解析建表 SQL 语句,返回 {@link SchemaTableDO} 和 {@link SchemaColumnDO} 对象 + * 解析建表 SQL 语句,返回 {@link DatabaseTableDO} 和 {@link DatabaseColumnDO} 对象 * * @param sql 建表 SQL 语句 * @return 解析结果 */ - public static KeyValue> parse(String sql) { + public static KeyValue> parse(String sql) { // 解析 SQL 成 Statement SQLCreateTableStatement statement = parseCreateSQL(sql); // 解析 Table 表 - SchemaTableDO table = parseTable(statement); + DatabaseTableDO table = parseTable(statement); // 解析 Column 字段 - List columns = parseColumns(statement); + List columns = parseColumns(statement); columns.forEach(column -> column.setTableName(table.getTableName())); // 返回 return new DefaultKeyValue<>(table, columns); @@ -61,8 +61,8 @@ public class CodegenSQLParser { return (MySqlCreateTableStatement) repository.findTable(tableName).getStatement(); } - private static SchemaTableDO parseTable(SQLCreateTableStatement statement) { - return SchemaTableDO.builder() + private static DatabaseTableDO parseTable(SQLCreateTableStatement statement) { + return DatabaseTableDO.builder() .tableName(statement.getTableSource().getTableName(true)) .tableComment(getCommentText(statement)) .build(); @@ -75,13 +75,13 @@ public class CodegenSQLParser { return ((SQLCharExpr) statement.getComment()).getText(); } - private static List parseColumns(SQLCreateTableStatement statement) { - List columns = new ArrayList<>(); + private static List parseColumns(SQLCreateTableStatement statement) { + List columns = new ArrayList<>(); statement.getTableElementList().forEach(element -> parseColumn(columns, element)); return columns; } - private static void parseColumn(List columns, SQLTableElement element) { + private static void parseColumn(List columns, SQLTableElement element) { // 处理主键 if (element instanceof SQLPrimaryKey) { parsePrimaryKey(columns, (SQLPrimaryKey) element); @@ -93,16 +93,16 @@ public class CodegenSQLParser { } } - private static void parsePrimaryKey(List columns, SQLPrimaryKey primaryKey) { + private static void parsePrimaryKey(List columns, SQLPrimaryKey primaryKey) { String columnName = normalize(primaryKey.getColumns().get(0).toString()); // 暂时不考虑联合主键 // 匹配 columns 主键字段,设置为 primary columns.stream().filter(column -> column.getColumnName().equals(columnName)) .forEach(column -> column.setPrimaryKey(true)); } - private static void parseColumnDefinition(List columns, SQLColumnDefinition definition) { + private static void parseColumnDefinition(List columns, SQLColumnDefinition definition) { String text = definition.toString().toUpperCase(); - columns.add(SchemaColumnDO.builder() + columns.add(DatabaseColumnDO.builder() .columnName(normalize(definition.getColumnName())) .columnType(definition.getDataType().toString()) .columnComment(Objects.isNull(definition.getComment()) ? "" diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java index b5e9e21ee..e7b2d9c5f 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.infra.service.db; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; -import org.w3c.dom.stylesheets.LinkStyle; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; import javax.validation.Valid; import java.util.List; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java index e2f1a6559..e591f259a 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java @@ -1,22 +1,21 @@ package cn.iocoder.yudao.module.infra.service.db; -import cn.hutool.db.DbUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; -import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; import org.jasypt.encryption.StringEncryptor; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.sql.Connection; import java.util.List; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DATA_SOURCE_CONFIG_NOT_EXISTS; @@ -37,6 +36,9 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @Resource private StringEncryptor stringEncryptor; + @Resource + private DynamicDataSourceProperties dynamicDataSourceProperties; + @Override public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) { DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO); @@ -77,6 +79,11 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @Override public DataSourceConfigDO getDataSourceConfig(Long id) { + // 如果 id 为 0,默认为 master 的数据源 + if (Objects.equals(id, DataSourceConfigDO.ID_MASTER)) { + return buildMasterDataSourceConfig(); + } + // 从 DB 中读取 DataSourceConfigDO dataSourceConfig = dataSourceConfigMapper.selectById(id); dataSourceConfig.setPassword(stringEncryptor.decrypt(dataSourceConfig.getPassword())); return dataSourceConfig; @@ -84,14 +91,26 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { @Override public List getDataSourceConfigList() { - return dataSourceConfigMapper.selectList(); + List result = dataSourceConfigMapper.selectList(); + // 补充 master 数据源 + result.add(0, buildMasterDataSourceConfig()); + return result; } private void checkConnectionOK(DataSourceConfigDO config) { - boolean success = DatabaseUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword()); + boolean success = JdbcUtils.isConnectionOK(config.getUrl(), config.getUsername(), config.getPassword()); if (!success) { throw exception(DATA_SOURCE_CONFIG_NOT_OK); } } + private DataSourceConfigDO buildMasterDataSourceConfig() { + String primary = dynamicDataSourceProperties.getPrimary(); + DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource().get(primary); + return new DataSourceConfigDO().setId(DataSourceConfigDO.ID_MASTER).setName(primary) + .setUrl(dataSourceProperty.getUrl()) + .setUsername(dataSourceProperty.getUsername()) + .setPassword(dataSourceProperty.getPassword()); + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java new file mode 100644 index 000000000..426d88639 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableService.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; + +import java.util.List; + +/** + * 数据库表 Service + * + * @author 芋道源码 + */ +public interface DatabaseTableService { + + /** + * 获得表列表,基于表名称 + 表描述进行模糊匹配 + * + * @param dataSourceConfigId 数据源配置的编号 + * @param tableNameLike 表名称,模糊匹配 + * @param tableCommentLike 表描述,模糊匹配 + * @return 表列表 + */ + List getTableList(Long dataSourceConfigId, String tableNameLike, String tableCommentLike); + + /** + * 获得指定表名 + * + * @param dataSourceConfigId 数据源配置的编号 + * @param tableName 表名称 + * @return 表 + */ + DatabaseTableDO getTable(Long dataSourceConfigId, String tableName); + + /** + * 获得指定表的字段列表 + * + * @param dataSourceConfigId 数据源配置的编号 + * @param tableName 表名称 + * @return 字段列表 + */ + List getColumnList(Long dataSourceConfigId, String tableName); + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java new file mode 100644 index 000000000..234e6d4a6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DatabaseTableServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.infra.service.db; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseColumnDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.db.DatabaseTableDO; +import cn.iocoder.yudao.module.infra.dal.mysql.db.DatabaseTableDAO; +import com.baomidou.mybatisplus.annotation.DbType; +import lombok.SneakyThrows; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.sql.Connection; +import java.util.List; + +/** + * 数据库表 Service 实现类 + * + * @author 芋道源码 + */ +@Service +public class DatabaseTableServiceImpl implements DatabaseTableService { + + @Resource + private DataSourceConfigService dataSourceConfigService; + + @Resource + private List databaseTableDAOs; + + @Override + @SneakyThrows + public List getTableList(Long dataSourceConfigId, String tableNameLike, String tableCommentLike) { + try (Connection connection = getConnection(dataSourceConfigId)) { + return getDatabaseTableDAO(dataSourceConfigId).selectTableList(connection, tableNameLike, tableCommentLike); + } + } + + @Override + @SneakyThrows + public DatabaseTableDO getTable(Long dataSourceConfigId, String tableName) { + try (Connection connection = getConnection(dataSourceConfigId)) { + return getDatabaseTableDAO(dataSourceConfigId).selectTable(connection, tableName); + } + } + + @Override + @SneakyThrows + public List getColumnList(Long dataSourceConfigId, String tableName) { + try (Connection connection = getConnection(dataSourceConfigId)) { + return getDatabaseTableDAO(dataSourceConfigId).selectColumnList(connection, tableName); + } + } + + private Connection getConnection(Long dataSourceConfigId) { + DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(dataSourceConfigId); + Assert.notNull(config, "数据源({}) 不存在!", dataSourceConfigId); + return JdbcUtils.getConnection(config.getUrl(), config.getUsername(), config.getPassword()); + } + + private DatabaseTableDAO getDatabaseTableDAO(Long dataSourceConfigId) { + DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(dataSourceConfigId); + Assert.notNull(config, "数据源({}) 不存在!", dataSourceConfigId); + // 获得 dbType + DbType dbType = JdbcUtils.getDbType(config.getUrl()); + Assert.notNull(config, "数据源类型({}) 不存在!", config.getUrl()); + // 获得 DatabaseTableDAO + DatabaseTableDAO dao = CollUtil.findOne(databaseTableDAOs, databaseTableDAO -> databaseTableDAO.getType().equals(dbType)); + Assert.notNull(dao, "DAO({}) 查找不到实现!", dbType); + return dao; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java index 5c51b198e..583730cde 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImplTest.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.service.db; -import cn.iocoder.yudao.framework.mybatis.core.util.DatabaseUtils; +import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; @@ -41,12 +41,12 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { @Test public void testCreateDataSourceConfig_success() { - try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + try (MockedStatic databaseUtilsMock = mockStatic(JdbcUtils.class)) { // 准备参数 DataSourceConfigCreateReqVO reqVO = randomPojo(DataSourceConfigCreateReqVO.class); // mock 方法 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); - databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()), eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); // 调用 @@ -62,7 +62,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateDataSourceConfig_success() { - try (MockedStatic databaseUtilsMock = mockStatic(DatabaseUtils.class)) { + try (MockedStatic databaseUtilsMock = mockStatic(JdbcUtils.class)) { // mock 数据 DataSourceConfigDO dbDataSourceConfig = randomPojo(DataSourceConfigDO.class); dataSourceConfigMapper.insert(dbDataSourceConfig);// @Sql: 先插入出一条存在的数据 @@ -72,7 +72,7 @@ public class DataSourceConfigServiceImplTest extends BaseDbUnitTest { }); // mock 方法 when(stringEncryptor.encrypt(eq(reqVO.getPassword()))).thenReturn("123456"); - databaseUtilsMock.when(() -> DatabaseUtils.isConnectionOK(eq(reqVO.getUrl()), + databaseUtilsMock.when(() -> JdbcUtils.isConnectionOK(eq(reqVO.getUrl()), eq(reqVO.getUsername()), eq(reqVO.getPassword()))).thenReturn(true); // 调用 From 3950c58c18065d9b09df0cb5c200a380594063d5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 28 Apr 2022 20:42:13 +0800 Subject: [PATCH 04/23] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Oracle=20Driver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-mybatis/pom.xml | 5 ++ .../admin/codegen/CodegenController.java | 8 ++-- .../admin/config/vo/ConfigPageReqVO.java | 2 +- .../admin/db/vo/DataSourceConfigBaseVO.java | 4 +- .../infra/service/codegen/CodegenService.java | 4 +- .../service/codegen/CodegenServiceImpl.java | 9 +--- .../src/views/infra/codegen/importTable.vue | 48 ++++++++++--------- .../views/infra/dataSourceConfig/index.vue | 6 +-- 8 files changed, 47 insertions(+), 39 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index db10906e9..bb394b0f3 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -38,6 +38,11 @@ mysql-connector-java ${mysql.version} + + com.oracle.database.jdbc + ojdbc8 + + com.alibaba druid-spring-boot-starter diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java index 40bd69271..2959dd511 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java @@ -50,15 +50,17 @@ public class CodegenController { @GetMapping("/db/table/list") @ApiOperation(value = "获得数据库自带的表定义列表", notes = "会过滤掉已经导入 Codegen 的表") @ApiImplicitParams({ - @ApiImplicitParam(name = "tableName", value = "表名,模糊匹配", required = true, example = "yudao", dataTypeClass = String.class), - @ApiImplicitParam(name = "tableComment", value = "描述,模糊匹配", required = true, example = "芋道", dataTypeClass = String.class) + @ApiImplicitParam(name = "dataSourceConfigId", value = "数据源配置的编号", required = true, example = "1", dataTypeClass = Long.class), + @ApiImplicitParam(name = "tableName", value = "表名,模糊匹配", example = "yudao", dataTypeClass = String.class), + @ApiImplicitParam(name = "tableComment", value = "描述,模糊匹配", example = "芋道", dataTypeClass = String.class) }) @PreAuthorize("@ss.hasPermission('infra:codegen:query')") public CommonResult> getSchemaTableList( + @RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId, @RequestParam(value = "tableName", required = false) String tableName, @RequestParam(value = "tableComment", required = false) String tableComment) { // 获得数据库自带的表定义列表 - List schemaTables = codegenService.getSchemaTableList(tableName, tableComment); + List schemaTables = codegenService.getSchemaTableList(dataSourceConfigId, tableName, tableComment); // 移除在 Codegen 中,已经存在的 Set existsTables = CollectionUtils.convertSet(codegenService.getCodeGenTableList(), CodegenTableDO::getTableName); schemaTables.removeIf(table -> existsTables.contains(table.getTableName())); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java index 87d4ce928..3f2b1eb61 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigPageReqVO.java @@ -18,7 +18,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class ConfigPageReqVO extends PageParam { - @ApiModelProperty(value = "参数名称", example = "模糊匹配") + @ApiModelProperty(value = "数据源名称", example = "模糊匹配") private String name; @ApiModelProperty(value = "参数键名", example = "yunai.db.username", notes = "模糊匹配") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java index ae3d97dce..dbf25b75c 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java @@ -12,8 +12,8 @@ import javax.validation.constraints.*; @Data public class DataSourceConfigBaseVO { - @ApiModelProperty(value = "参数名称", required = true, example = "test") - @NotNull(message = "参数名称不能为空") + @ApiModelProperty(value = "数据源名称", required = true, example = "test") + @NotNull(message = "数据源名称不能为空") private String name; @ApiModelProperty(value = "数据源连接", required = true, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java index 7d3951afa..d02c6225d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java @@ -115,10 +115,12 @@ public interface CodegenService { /** * 获得数据库自带的表定义列表 * + * + * @param dataSourceConfigId * @param tableName 表名称 * @param tableComment 表描述 * @return 表定义列表 */ - List getSchemaTableList(String tableName, String tableComment); + List getSchemaTableList(Long dataSourceConfigId, String tableName, String tableComment); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java index cdeda9d67..29ae9c486 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java @@ -57,9 +57,6 @@ public class CodegenServiceImpl implements CodegenService { @Resource private CodegenEngine codegenEngine; - @Resource - private CodegenProperties codegenProperties; - private Long createCodegen0(Long userId, CodegenImportTypeEnum importType, DatabaseTableDO schemaTable, List schemaColumns) { // 校验导入的表和字段非空 @@ -103,8 +100,6 @@ public class CodegenServiceImpl implements CodegenService { @Override public Long createCodegen(Long userId, String tableName) { - // 获取当前schema - String tableSchema = codegenProperties.getDbSchemas().iterator().next(); // 从数据库中,获得数据库表结构 DatabaseTableDO schemaTable = databaseTableService.getTable(0L, tableName); List schemaColumns = databaseTableService.getColumnList(0L, tableName); @@ -252,8 +247,8 @@ public class CodegenServiceImpl implements CodegenService { } @Override - public List getSchemaTableList(String tableName, String tableComment) { - List tables = databaseTableService.getTableList(0L, tableName, tableComment); + public List getSchemaTableList(Long dataSourceConfigId, String tableName, String tableComment) { + List tables = databaseTableService.getTableList(dataSourceConfigId, tableName, tableComment); // TODO 强制移除 Quartz 的表,未来做成可配置 tables.removeIf(table -> table.getTableName().startsWith("QRTZ_")); tables.removeIf(table -> table.getTableName().startsWith("ACT_")); diff --git a/yudao-ui-admin/src/views/infra/codegen/importTable.vue b/yudao-ui-admin/src/views/infra/codegen/importTable.vue index 726a014e3..4ff51f3ba 100644 --- a/yudao-ui-admin/src/views/infra/codegen/importTable.vue +++ b/yudao-ui-admin/src/views/infra/codegen/importTable.vue @@ -1,24 +1,18 @@