Commit aec5a2d5 authored by 林洋洋's avatar 林洋洋

数据源展示,数据展示接口修改

parent 5981f91d
FROM registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/mysql-server:8.0.32
MAINTAINER lengleng(wangiegie@gmail.com)
ENV TZ=Asia/Shanghai
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY ./pig.sql /docker-entrypoint-initdb.d
COPY ./pig_config.sql /docker-entrypoint-initdb.d
EXPOSE 3306
This diff is collapsed.
This diff is collapsed.
package com.pig4cloud.pig.ask.api.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class TableDto {
/**
* 表名
*/
@Schema(description = "表名")
private String tableName;
/**
* 表名
*/
@Schema(description = "表注释")
private String tableComment;
}
package com.pig4cloud.pig.ask.api.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class TableParam {
@Schema(description = "数据源名称")
private String dsName;
/**
* 数据源类型
*/
@Schema(description = "数据源类型")
private String dbType;
/**
* 表名
*/
@Schema(description = "表名")
private String tableName;
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 数据源表
*
* @author lengleng
* @date 2019-03-31 16:00:20
*/
@Data
@TableName("gen_datasource_conf")
@EqualsAndHashCode(callSuper = true)
public class GenDatasourceConf extends Model<GenDatasourceConf> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 名称
*/
private String name;
/**
* 数据库类型
*/
private String dsType;
/**
* 配置类型 (0 主机形式 | 1 url形式)
*/
private Integer confType;
/**
* 主机地址
*/
private String host;
/**
* 端口
*/
private Integer port;
/**
* jdbc-url
*/
private String url;
/**
* 实例
*/
private String instance;
/**
* 数据库名称
*/
private String dsName;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 修改时间
*/
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/**
* 0-正常,1-删除
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
private String delFlag;
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
import java.util.List;
/**
* 列属性
*
* @author pigx code generator
* @date 2023-02-06 20:34:55
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "列属性")
public class GenTable extends Model<GenTable> {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "id")
private Long id;
/**
* 数据源名称
*/
@Schema(description = "数据源名称")
private String dsName;
/**
* 数据源类型
*/
@Schema(description = "数据源类型")
private String dbType;
/**
* 表名
*/
@Schema(description = "表名")
private String tableName;
/**
* 类名
*/
@Schema(description = "类名")
private String className;
/**
* 说明
*/
@Schema(description = "说明")
private String tableComment;
/**
* 作者
*/
@Schema(description = "作者")
private String author;
/**
* 邮箱
*/
@Schema(description = "邮箱")
private String email;
/**
* 项目包名
*/
@Schema(description = "项目包名")
private String packageName;
/**
* 项目版本号
*/
@Schema(description = "项目版本号")
private String version;
/**
* 生成方式 0:zip压缩包 1:自定义目录
*/
@Schema(description = "生成方式 0:zip压缩包 1:自定义目录")
private String generatorType;
/**
* 后端生成路径
*/
@Schema(description = "后端生成路径")
private String backendPath;
/**
* 前端生成路径
*/
@Schema(description = "前端生成路径")
private String frontendPath;
/**
* 模块名
*/
@Schema(description = "模块名")
private String moduleName;
/**
* 功能名
*/
@Schema(description = "功能名")
private String functionName;
/**
* 表单布局 1:一列 2:两列
*/
@Schema(description = "表单布局 1:一列 2:两列")
private Integer formLayout;
/**
* 基类ID
*/
@Schema(description = "基类ID")
private Long baseclassId;
/**
* 创建时间
*/
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 代码生成风格
*/
private Long style;
/**
* 子表名称
*/
private String childTableName;
/**
* 主表关联键
*/
private String mainField;
/**
* 子表关联键
*/
private String childField;
// /**
// * 字段列表
// */
// @TableField(exist = false)
// private List<GenTableColumnEntity> fieldList;
//
// /**
// * 子表字段列表
// */
// @TableField(exist = false)
// private List<GenTableColumnEntity> childFieldList;
// /**
// * 代码风格(模版分组信息)
// */
// @TableField(exist = false)
// private List<GenGroupEntity> groupList;
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @author lengleng
* @date 2023-02-06
*
* 记录表字段的配置信息
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class GenTableColumnEntity extends Model<GenDatasourceConf> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 数据源名
*/
private String dsName;
/**
* 表名称
*/
private String tableName;
/**
* 字段名称
*/
private String fieldName;
/**
* 排序
*/
private Integer sort;
/**
* 字段类型
*/
private String fieldType;
/**
* 字段说明
*/
private String fieldComment;
/**
* 属性名
*/
private String attrName;
/**
* 属性类型
*/
private String attrType;
/**
* 属性包名
*/
private String packageName;
/**
* 自动填充
*/
private String autoFill;
/**
* 主键 0:否 1:是
*/
private String primaryPk;
/**
* 基类字段 0:否 1:是
*/
private String baseField;
/**
* 表单项 0:否 1:是
*/
private String formItem;
/**
* 表单必填 0:否 1:是
*/
private String formRequired;
/**
* 表单类型
*/
private String formType;
/**
* 表单效验
*/
private String formValidator;
/**
* 列表项 0:否 1:是
*/
private String gridItem;
/**
* 列表排序 0:否 1:是
*/
private String gridSort;
/**
* 查询项 0:否 1:是
*/
private String queryItem;
/**
* 查询方式
*/
private String queryType;
/**
* 查询表单类型
*/
private String queryFormType;
/**
* 字段字典类型
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String fieldDict;
}
package com.pig4cloud.pig.ask.api.enums;
/**
* 字段自动填充 枚举
*
* @author 阿沐 babamu@126.com
*/
public enum AutoFillEnum {
DEFAULT, INSERT, UPDATE, INSERT_UPDATE, CREATE;
}
package com.pig4cloud.pig.ask.api.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* boolean 类型枚举
*
*/
@Getter
@RequiredArgsConstructor
public enum BoolFillEnum {
/**
* true
*/
TRUE("1"),
/**
* false
*/
FALSE("0");
private final String value;
}
package com.pig4cloud.pig.ask.api.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author lengleng
* @date 2023/3/12
* <p>
* 通用字段的填充策略和显示策略
*/
@Getter
@AllArgsConstructor
public enum CommonColumnFiledEnum {
/**
* create_by 字段
*/
create_by("0", "0", AutoFillEnum.INSERT.name(), 100),
/**
* create_time 字段
*/
create_time("0", "0", AutoFillEnum.INSERT.name(), 101),
/**
* update_by 字段
*/
update_by("0", "0", AutoFillEnum.INSERT_UPDATE.name(), 102),
/**
* update_time 字段
*/
update_time("0", "0", AutoFillEnum.INSERT_UPDATE.name(), 103),
/**
* del_flag 字段
*/
del_flag("0", "0", AutoFillEnum.DEFAULT.name(), 104),
/**
* tenant_id 字段
*/
tenant_id("0", "0", AutoFillEnum.DEFAULT.name(), 105);
/**
* 表单是否默认显示 1/0
*/
private String formItem;
/**
* 表格是否默认显示 1/0
*/
private String gridItem;
/**
* 自动填充策略
*/
private String autoFill;
/**
* 排序值
*/
private Integer sort;
}
...@@ -28,7 +28,10 @@ ...@@ -28,7 +28,10 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<description>pig AI智能问答管理模块</description> <description>pig AI智能问答管理模块</description>
<properties>
<anyline.version>8.7.2-jdk17-20240808</anyline.version>
</properties>
<dependencies> <dependencies>
<!-- ask api、model 模块--> <!-- ask api、model 模块-->
<dependency> <dependency>
...@@ -65,6 +68,25 @@ ...@@ -65,6 +68,25 @@
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency> </dependency>
<!--数据操作-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-mybatis</artifactId>
</dependency>
<!--动态数据源 数据操作-->
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pig-common-datasource</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- PostgreSQL驱动 --> <!-- PostgreSQL驱动 -->
<dependency> <dependency>
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
...@@ -95,6 +117,16 @@ ...@@ -95,6 +117,16 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId> <artifactId>spring-boot-starter-undertow</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.anyline</groupId>
<artifactId>anyline-environment-spring-data-jdbc</artifactId>
<version>${anyline.version}</version>
</dependency>
<dependency>
<groupId>org.anyline</groupId>
<artifactId>anyline-data-jdbc-mysql</artifactId>
<version>${anyline.version}</version>
</dependency>
</dependencies> </dependencies>
<profiles> <profiles>
......
package com.pig4cloud.pig.ask.config;
import com.pig4cloud.pig.ask.api.entity.GenDatasourceConf;
import com.pig4cloud.pig.ask.service.GenDatasourceConfService;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class InitDataBase implements CommandLineRunner {
@Autowired
private GenDatasourceConfService genDatasourceConfService;
@Autowired
private StringEncryptor stringEncryptor;
@Override
public void run(String... args) throws Exception {
List<GenDatasourceConf> genDatasourceConfList = genDatasourceConfService.list();
genDatasourceConfList.forEach(conf->{
conf.setPassword(stringEncryptor.decrypt(conf.getPassword()));
genDatasourceConfService.addDynamicDataSource(conf);
});
}
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.controller;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.ask.api.entity.GenDatasourceConf;
import com.pig4cloud.pig.ask.service.GenDatasourceConfService;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.security.annotation.Inner;
import com.pig4cloud.pig.common.xss.core.XssCleanIgnore;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import javax.sql.DataSource;
/**
* 数据源管理控制器
*
* @author lengleng
* @date 2025/05/31
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/dsconf")
public class GenDsConfController {
private final GenDatasourceConfService datasourceConfService;
/**
* 分页查询数据源配置
* @param page 分页参数对象
* @param datasourceConf 数据源配置查询条件
* @return 分页查询结果
*/
@GetMapping("/page")
public R getDsConfPage(Page page, GenDatasourceConf datasourceConf) {
return R.ok(datasourceConfService.page(page,
Wrappers.<GenDatasourceConf>lambdaQuery()
.like(StrUtil.isNotBlank(datasourceConf.getDsName()), GenDatasourceConf::getDsName,
datasourceConf.getDsName())));
}
/**
* 查询全部数据源列表
* @return 包含全部数据源列表的响应结果
*/
@GetMapping("/list")
@Inner(value = false)
public R listDsConfs() {
return R.ok(datasourceConfService.list());
}
/**
* 根据ID查询数据源表
* @param id 数据源ID
* @return 包含查询结果的响应对象
*/
@GetMapping("/{id}")
public R getDsConfById(@PathVariable("id") Long id) {
return R.ok(datasourceConfService.getById(id));
}
/**
* 新增数据源表
* @param datasourceConf 数据源配置信息
* @return 操作结果
*/
@PostMapping
@XssCleanIgnore
public R saveDsConf(@RequestBody GenDatasourceConf datasourceConf) {
return R.ok(datasourceConfService.saveDsByEnc(datasourceConf));
}
/**
* 修改数据源表
* @param conf 数据源表配置信息
* @return 操作结果
*/
@PutMapping
@XssCleanIgnore
public R updateDsConf(@RequestBody GenDatasourceConf conf) {
return R.ok(datasourceConfService.updateDsByEnc(conf));
}
/**
* 通过id数组删除数据源表
* @param ids 要删除的数据源id数组
* @return 包含操作结果的R对象
*/
@DeleteMapping
public R removeDsConfByIds(@RequestBody Long[] ids) {
return R.ok(datasourceConfService.removeByDsId(ids));
}
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.ask.api.dto.TableDto;
import com.pig4cloud.pig.ask.api.dto.TableParam;
import com.pig4cloud.pig.ask.api.entity.GenTable;
import com.pig4cloud.pig.ask.api.entity.GenTableColumnEntity;
import com.pig4cloud.pig.ask.service.GenTableService;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.log.annotation.SysLog;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 代码表管理控制器
*
* @author lengleng
* @date 2025/05/31
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/table")
@Tag(description = "table", name = "代码表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class GenTableController {
/**
* 表服务
*/
private final GenTableService tableService;
/**
* 分页查询
* @param page 分页对象
* @param table 列属性
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
public R<IPage<TableDto>> getTablePage(Page page, TableParam table) {
return R.ok(tableService.queryTablePage(page, table));
}
/**
* 通过id查询表信息(代码生成设置 + 表 + 字段设置)
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
public R getTableById(@PathVariable("id") Long id) {
return R.ok(tableService.getById(id));
}
/**
* 查询数据源所有表
* @param dsName 数据源名称
* @return 包含表列表的响应结果
*/
@GetMapping("/list/{dsName}")
public R listTables(@PathVariable("dsName") String dsName) {
return R.ok(tableService.queryTableList(dsName));
}
// /**
// * 获取表信息
// * @param dsName 数据源
// * @param tableName 表名称
// */
// @GetMapping("/{dsName}/{tableName}")
// public R<GenTable> getTable(@PathVariable("dsName") String dsName, @PathVariable String tableName) {
// return R.ok(tableService.queryOrBuildTable(dsName, tableName));
// }
/**
* 查询表DDL语句
* @param dsName 数据源
* @param tableName 表名称
*/
@GetMapping("/column/{dsName}/{tableName}")
public R getTableColumn(@PathVariable("dsName") String dsName, @PathVariable String tableName) throws Exception {
return R.ok(tableService.queryTableColumn(dsName, tableName));
}
/**
* 查询表DDL语句
* @param dsName 数据源
* @param tableName 表名称
*/
@GetMapping("/ddl/{dsName}/{tableName}")
public R getTableDdl(@PathVariable("dsName") String dsName, @PathVariable String tableName) throws Exception {
return R.ok(tableService.queryTableDdl(dsName, tableName));
}
// /**
// * 同步表信息
// * @param dsName 数据源
// * @param tableName 表名称
// */
// @GetMapping("/sync/{dsName}/{tableName}")
// public R<GenTable> syncTable(@PathVariable("dsName") String dsName, @PathVariable String tableName) {
// // 表配置删除
// tableService.remove(
// Wrappers.<GenTable>lambdaQuery().eq(GenTable::getDsName, dsName).eq(GenTable::getTableName, tableName));
// // 字段配置删除
// tableColumnService.remove(Wrappers.<GenTableColumnEntity>lambdaQuery()
// .eq(GenTableColumnEntity::getDsName, dsName)
// .eq(GenTableColumnEntity::getTableName, tableName));
// return R.ok(tableService.queryOrBuildTable(dsName, tableName));
// }
// /**
// * 修改列属性
// * @param table 列属性
// * @return R
// */
// @Operation(summary = "修改列属性", description = "修改列属性")
// @SysLog("修改列属性")
// @PutMapping
// public R updateTable(@RequestBody GenTable table) {
// return R.ok(tableService.updateById(table));
// }
//
// /**
// * 修改表字段数据
// * @param dsName 数据源
// * @param tableName 表名称
// * @param tableFieldList 字段列表
// */
// @PutMapping("/field/{dsName}/{tableName}")
// public R<String> updateTableField(@PathVariable("dsName") String dsName, @PathVariable String tableName,
// @RequestBody List<GenTableColumnEntity> tableFieldList) {
// tableColumnService.updateTableField(dsName, tableName, tableFieldList);
// return R.ok();
// }
// /**
// * 导出excel 表格
// * @param table 查询条件
// * @return excel 文件流
// */
// @ResponseExcel
// @GetMapping("/export")
// public List<GenTable> exportTables(GenTable table) {
// return tableService.list(Wrappers.query(table));
// }
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pig.ask.api.entity.GenDatasourceConf;
import org.apache.ibatis.annotations.Mapper;
/**
* 数据源表 Mapper 接口
*
* @author lengleng
* @date 2019-03-31 16:00:20
*/
@Mapper
public interface GenDatasourceConfMapper extends BaseMapper<GenDatasourceConf> {
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pig.ask.api.entity.GenTable;
import org.apache.ibatis.annotations.Mapper;
/**
* 代码生成表 Mapper 接口
*
* @author lengleng
* @date 2025/05/31
*/
@Mapper
public interface GenTableMapper extends BaseMapper<GenTable> {
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pig.ask.api.entity.GenDatasourceConf;
/**
* 数据源配置服务接口 提供数据源的增删改查及校验等功能
*
* @author lengleng
* @date 2025/05/31
*/
public interface GenDatasourceConfService extends IService<GenDatasourceConf> {
/**
* 保存数据源并加密
* @param genDatasourceConf 数据源配置信息
* @return 保存是否成功
*/
Boolean saveDsByEnc(GenDatasourceConf genDatasourceConf);
/**
* 更新数据源
* @param genDatasourceConf 数据源配置信息
* @return 更新是否成功
*/
Boolean updateDsByEnc(GenDatasourceConf genDatasourceConf);
/**
* 添加动态数据源
* @param datasourceConf 数据源配置信息
*/
void addDynamicDataSource(GenDatasourceConf datasourceConf);
/**
* 校验数据源配置是否有效
* @param datasourceConf 数据源配置信息
* @return true表示有效,false表示无效
*/
Boolean checkDataSource(GenDatasourceConf datasourceConf);
/**
* 通过数据源ID删除数据源
* @param dsIds 数据源ID数组
* @return 删除是否成功
*/
Boolean removeByDsId(Long[] dsIds);
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pig.ask.api.dto.TableDto;
import com.pig4cloud.pig.ask.api.dto.TableParam;
import com.pig4cloud.pig.ask.api.entity.GenTable;
import org.anyline.metadata.Table;
import java.util.List;
/**
* 代码生成表服务接口
*
* @author lengleng
* @date 2025/05/31
*/
public interface GenTableService extends IService<GenTable> {
/**
* 查询对应数据源的表
* @param page 分页信息
* @param table 查询条件
* @return 表
*/
IPage<TableDto> queryTablePage(Page<TableDto> page, TableParam table);
/**
* 查询表ddl 语句
* @param dsName 数据源名称
* @param tableName 表名称
* @return ddl 语句
* @throws Exception
*/
String queryTableDdl(String dsName, String tableName) throws Exception;
/**
* 查询数据源里面的全部表
* @param dsName 数据源名称
* @return table
*/
List<String> queryTableList(String dsName);
/**
* 查询表的全部字段
* @param dsName 数据源
* @param tableName 表名称
* @return column
*/
List<String> queryTableColumn(String dsName, String tableName);
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pig.ask.api.entity.GenDatasourceConf;
import com.pig4cloud.pig.ask.mapper.GenDatasourceConfMapper;
import com.pig4cloud.pig.ask.service.GenDatasourceConfService;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.datasource.enums.DsConfTypeEnum;
import com.pig4cloud.pig.common.datasource.enums.DsJdbcUrlEnum;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jasypt.encryption.StringEncryptor;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
/**
* 数据源配置服务实现类
*
* <p>
* 提供数据源的增删改查及校验功能,支持数据源密码加密存储
* </p>
*
* @author lengleng
* @date 2025/05/31
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class GenDatasourceConfServiceImpl extends ServiceImpl<GenDatasourceConfMapper, GenDatasourceConf>
implements GenDatasourceConfService {
private final StringEncryptor stringEncryptor;
private final DataSourceCreator hikariDataSourceCreator;
/**
* 保存数据源配置并进行加密处理
* @param conf 数据源配置信息
* @return 保存成功返回true,失败返回false
*/
@Override
public Boolean saveDsByEnc(GenDatasourceConf conf) {
// 校验配置合法性
if (!checkDataSource(conf)) {
return Boolean.FALSE;
}
// 添加动态数据源
addDynamicDataSource(conf);
// 更新数据库配置
conf.setPassword(stringEncryptor.encrypt(conf.getPassword()));
this.baseMapper.insert(conf);
return Boolean.TRUE;
}
/**
* 更新加密数据源
* @param conf 数据源配置信息
* @return 更新成功返回true,失败返回false
*/
@Override
public Boolean updateDsByEnc(GenDatasourceConf conf) {
if (!checkDataSource(conf)) {
return Boolean.FALSE;
}
// 先移除
DynamicRoutingDataSource dynamicRoutingDataSource = SpringContextHolder.getBean(DynamicRoutingDataSource.class);
dynamicRoutingDataSource.removeDataSource(baseMapper.selectById(conf.getId()).getName());
// 再添加
addDynamicDataSource(conf);
// 更新数据库配置
if (StrUtil.isNotBlank(conf.getPassword())) {
conf.setPassword(stringEncryptor.encrypt(conf.getPassword()));
}
this.baseMapper.updateById(conf);
return Boolean.TRUE;
}
/**
* 通过数据源ID删除数据源
* @param dsIds 数据源ID数组
* @return 删除是否成功
*/
@Override
public Boolean removeByDsId(Long[] dsIds) {
DynamicRoutingDataSource dynamicRoutingDataSource = SpringContextHolder.getBean(DynamicRoutingDataSource.class);
this.baseMapper.selectByIds(CollUtil.toList(dsIds))
.forEach(ds -> dynamicRoutingDataSource.removeDataSource(ds.getName()));
this.baseMapper.deleteByIds(CollUtil.toList(dsIds));
return Boolean.TRUE;
}
/**
* 添加动态数据源
* @param conf 数据源配置信息
*/
@Override
public void addDynamicDataSource(GenDatasourceConf conf) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
dataSourceProperty.setPoolName(conf.getName());
dataSourceProperty.setUrl(conf.getUrl());
dataSourceProperty.setUsername(conf.getUsername());
dataSourceProperty.setPassword(conf.getPassword());
DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
DynamicRoutingDataSource dynamicRoutingDataSource = SpringContextHolder.getBean(DynamicRoutingDataSource.class);
dynamicRoutingDataSource.addDataSource(dataSourceProperty.getPoolName(), dataSource);
}
/**
* 校验数据源配置是否有效
* @param conf 数据源配置信息
* @return 数据源配置是否有效,true表示有效
* @throws RuntimeException 数据库连接失败时抛出异常
*/
@Override
public Boolean checkDataSource(GenDatasourceConf conf) {
String url;
// JDBC 配置形式
if (DsConfTypeEnum.JDBC.getType().equals(conf.getConfType())) {
url = conf.getUrl();
}
else if (DsJdbcUrlEnum.MSSQL.getDbName().equals(conf.getDsType())) {
// 主机形式 sql server 特殊处理
DsJdbcUrlEnum urlEnum = DsJdbcUrlEnum.get(conf.getDsType());
url = String.format(urlEnum.getUrl(), conf.getHost(), conf.getPort(), conf.getDsName());
}
else {
DsJdbcUrlEnum urlEnum = DsJdbcUrlEnum.get(conf.getDsType());
url = String.format(urlEnum.getUrl(), conf.getHost(), conf.getPort(), conf.getDsName());
}
conf.setUrl(url);
try (Connection connection = DriverManager.getConnection(url, conf.getUsername(), conf.getPassword())) {
}
catch (SQLException e) {
log.error("数据源配置 {} , 获取链接失败", conf.getName(), e);
throw new RuntimeException("数据库配置错误,链接失败");
}
return Boolean.TRUE;
}
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pig.ask.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.NamingCase;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pig.ask.api.dto.TableDto;
import com.pig4cloud.pig.ask.api.dto.TableParam;
import com.pig4cloud.pig.ask.api.entity.GenTable;
import com.pig4cloud.pig.ask.api.entity.GenTableColumnEntity;
import com.pig4cloud.pig.ask.api.enums.AutoFillEnum;
import com.pig4cloud.pig.ask.api.enums.BoolFillEnum;
import com.pig4cloud.pig.ask.api.enums.CommonColumnFiledEnum;
import com.pig4cloud.pig.ask.mapper.GenTableMapper;
import com.pig4cloud.pig.ask.service.GenTableService;
import com.pig4cloud.pig.common.datasource.enums.DsJdbcUrlEnum;
import lombok.RequiredArgsConstructor;
import org.anyline.metadata.Column;
import org.anyline.metadata.Database;
import org.anyline.metadata.Schema;
import org.anyline.metadata.Table;
import org.anyline.proxy.CacheProxy;
import org.anyline.proxy.ServiceProxy;
import org.anyline.service.AnylineService;
import org.jetbrains.annotations.NotNull;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*;
/**
* 代码生成表服务实现类
*
* @author lengleng
* @date 2025/05/31
*/
@Service
@RequiredArgsConstructor
public class GenTableServiceImpl extends ServiceImpl<GenTableMapper, GenTable> implements GenTableService {
private final JdbcTemplate jdbcTemplate;
// private final GenGroupService genGroupService;
/**
* 查询表ddl 语句
*
* @param dsName 数据源名称
* @param tableName 表名称
* @return ddl 语句
* @throws Exception
*/
@Override
public String queryTableDdl(String dsName, String tableName) throws Exception {
// 手动切换数据源
DynamicDataSourceContextHolder.push(dsName);
Table table = ServiceProxy.metadata().table(tableName); // 获取表结构
table.execute(false);// 不执行SQL
ServiceProxy.ddl().create(table);
return table.getDdl();// 返回创建表的DDL
}
/**
* 查询表的全部字段
*
* @param dsName 数据源
* @param tableName 表名称
* @return column
*/
@Override
public List<String> queryTableColumn(String dsName, String tableName) {
// 手动切换数据源
DynamicDataSourceContextHolder.push(dsName);
CacheProxy.clear();
return ServiceProxy.metadata().columns(tableName).values().stream().map(Column::getName).toList();
}
/**
* 查询对应数据源的表
*
* @param page 分页信息
* @param table 查询条件
* @return 表
*/
@Override
public IPage<TableDto> queryTablePage(Page<TableDto> page, TableParam table) {
// 手动切换数据源
DynamicDataSourceContextHolder.push(table.getDsName());
CacheProxy.clear();
String sql = null;
if (DsJdbcUrlEnum.MYSQL.getDbName().equals(table.getDbType())) {
sql = "SELECT table_name,table_comment,create_time FROM information_schema.tables WHERE table_schema = (SELECT database()) AND table_type = 'BASE TABLE' ORDER BY table_name;";
} else if (DsJdbcUrlEnum.PG.getDbName().equals(table.getDbType())) {
sql = """
SELECT
t.table_name,
obj_description((t.table_schema || '.' || t.table_name)::regclass, 'pg_class') as table_comment
FROM
information_schema.tables t
WHERE
t.table_schema = current_schema()
AND t.table_type = 'BASE TABLE'
ORDER BY
t.table_name
""";
}
if (StringUtils.isBlank(sql)) {
return new Page<>(page.getCurrent(), page.getSize());
}
List<TableDto> tableList = jdbcTemplate.query(sql, (rs, rowNum) -> {
TableDto t = new TableDto();
t.setTableName(rs.getString("table_name"));
t.setTableComment(rs.getString("table_comment"));
return t;
});
tableList = tableList.stream().filter(t->{
if(StringUtils.isBlank(table.getTableName())){
return true;
}
return t.getTableName().equals(table.getTableName());
}).toList();
// 根据 page 进行分页
List<TableDto> records = CollUtil.page((int) page.getCurrent() - 1, (int) page.getSize(), tableList);
page.setTotal(tableList.size());
page.setRecords(records);
return page;
}
/**
* 查询数据源里面的全部表
*
* @param dsName 数据源名称
* @return table
*/
@Override
public List<String> queryTableList(String dsName) {
// 手动切换数据源
DynamicDataSourceContextHolder.push(dsName);
CacheProxy.clear();
AnylineService.MetaDataService metadata = ServiceProxy.metadata();
return ServiceProxy.metadata().tables().values().stream().map(Table::getName).toList();
}
/**
* 获取表字段信息
*
* @param dsName 数据源信息
* @param tableName 表名称
* @param tableMetadata 表的元数据
* @return list
*/
private static @NotNull List<GenTableColumnEntity> getGenTableColumnEntities(String dsName, String tableName,
Table tableMetadata) {
List<GenTableColumnEntity> tableFieldList = new ArrayList<>();
LinkedHashMap<String, Column> columns = tableMetadata.getColumns();
columns.forEach((columnName, column) -> {
GenTableColumnEntity genTableColumnEntity = new GenTableColumnEntity();
genTableColumnEntity.setTableName(tableName);
genTableColumnEntity.setDsName(dsName);
genTableColumnEntity.setFieldName(column.getName());
genTableColumnEntity.setFieldComment(column.getComment());
genTableColumnEntity.setFieldType(column.getTypeName());
genTableColumnEntity.setPrimaryPk(
column.isPrimaryKey() == 1 ? BoolFillEnum.TRUE.getValue() : BoolFillEnum.FALSE.getValue());
genTableColumnEntity.setAutoFill(AutoFillEnum.DEFAULT.name());
genTableColumnEntity.setFormItem(BoolFillEnum.TRUE.getValue());
genTableColumnEntity.setGridItem(BoolFillEnum.TRUE.getValue());
// 审计字段处理
if (EnumUtil.contains(CommonColumnFiledEnum.class, column.getName())) {
CommonColumnFiledEnum commonColumnFiledEnum = CommonColumnFiledEnum.valueOf(column.getName());
genTableColumnEntity.setFormItem(commonColumnFiledEnum.getFormItem());
genTableColumnEntity.setGridItem(commonColumnFiledEnum.getGridItem());
genTableColumnEntity.setAutoFill(commonColumnFiledEnum.getAutoFill());
genTableColumnEntity.setSort(commonColumnFiledEnum.getSort());
}
tableFieldList.add(genTableColumnEntity);
});
return tableFieldList;
}
}
FROM registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/java:21-anolis FROM registry.cn-hangzhou.aliyuncs.com/dockerhub_mirror/java:17-anolis
WORKDIR /pig-boot WORKDIR /pig-boot
......
...@@ -18,6 +18,7 @@ package com.pig4cloud.pig; ...@@ -18,6 +18,7 @@ package com.pig4cloud.pig;
import com.pig4cloud.pig.common.security.annotation.EnablePigResourceServer; import com.pig4cloud.pig.common.security.annotation.EnablePigResourceServer;
import com.pig4cloud.pig.common.swagger.annotation.EnablePigDoc; import com.pig4cloud.pig.common.swagger.annotation.EnablePigDoc;
import com.pig4cloud.pig.common.datasource.annotation.EnableDynamicDataSource;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
...@@ -29,6 +30,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; ...@@ -29,6 +30,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*/ */
@EnablePigDoc(value = "admin", isMicro = false) @EnablePigDoc(value = "admin", isMicro = false)
@EnablePigResourceServer @EnablePigResourceServer
@EnableDynamicDataSource
@SpringBootApplication @SpringBootApplication
public class PigBootApplication { public class PigBootApplication {
......
...@@ -3,16 +3,21 @@ spring: ...@@ -3,16 +3,21 @@ spring:
type: redis # 缓存类型 Redis type: redis # 缓存类型 Redis
data: data:
redis: redis:
database: 5 database: 6
host: 81.70.183.25 host: 81.70.183.25
port: 16379 port: 16379
password: '123qwe!@#' password: '123qwe!@#'
# 数据库相关配置 # 数据库相关配置
datasource: datasource:
driver-class-name: org.postgresql.Driver dynamic:
primary: master
strict: true
datasource:
master:
url: jdbc:postgresql://81.70.183.25:25432/ask_data_ai_db
username: postgres username: postgres
password: postgres123 password: postgres123
url: jdbc:postgresql://81.70.183.25:25432/ask_data_ai_db driver-class-name: org.postgresql.Driver
# 本地文件系统 # 本地文件系统
file: file:
......
server: server:
port: 19999 # 项目端口 port: 9999 # 项目端口
servlet: servlet:
context-path: /admin # 项目访问路径 context-path: /admin # 项目访问路径
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
<!-- 项目版本号 --> <!-- 项目版本号 -->
<revision>3.9.0</revision> <revision>3.9.0</revision>
<postgresql.version>42.6.2</postgresql.version> <postgresql.version>42.6.2</postgresql.version>
<mysql.version>9.2.0</mysql.version>
<spring-boot.version>3.5.0</spring-boot.version> <spring-boot.version>3.5.0</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
...@@ -108,6 +109,11 @@ ...@@ -108,6 +109,11 @@
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
<version>${postgresql.version}</version> <version>${postgresql.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--springdoc --> <!--springdoc -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
......
...@@ -27,7 +27,7 @@ public enum DsJdbcUrlEnum { ...@@ -27,7 +27,7 @@ public enum DsJdbcUrlEnum {
/** /**
* pg 数据库 * pg 数据库
*/ */
PG("pg", "jdbc:postgresql://%s:%s/%s", "select 1", "postgresql 链接"), PG("postgres", "jdbc:postgresql://%s:%s/%s", "select 1", "postgresql 链接"),
/** /**
* SQL SERVER * SQL SERVER
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment