# LowCode 低代码建表工具

news/2024/2/27 4:49:32

LowCode 低代码建表工具

需求描述

  • 将数据库的表映射为实体类,服务启动时,扫描表相关的实体类,根据实体类模型在数据库创建相关的表

依赖

  • 主要依赖:使用 Sprintboot、druid、spring-jdbc、mybatis
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.3</version>
</dependency><!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.11</version>
</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.8.RELEASE</version><scope>compile</scope>
</dependency><!-- Mybatis 的依赖  -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version>
</dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>RELEASE</version><scope>compile</scope>
</dependency>

设计思路

  • 使用Springboot CommandLineRunner机制
  • 开发自定义数据库模型表注解,扫描所有的表注解
  • 查询数据库库、表、字段等元数据信息
  • 比对元数据和扫描到的表模型信息,确定新增和更新的表模型
  • 执行新增和更新操作

代码工程

  • annotation:自定义数据库模型表、字段、索引等注解
  • init:主要扫描表信息,比对元数据建表的代码
  • constants:常量类
  • utils:工具类
    在这里插入图片描述

业务流程图

  • lowcode-database业务流程图大致如下
    在这里插入图片描述

类图

lowcode-database建表接口

  • 调用此接口中的方法进行建表的操作
    在这里插入图片描述

lowcode-database主要类图

  • 建表管理器,主要负责获取不同数据库的元数据信息,针对不同的数据库进行建表、更新表的操作

  • 总类图
    在这里插入图片描述

  • 放大部分图
    在这里插入图片描述

工厂类

在这里插入图片描述

自定义表注解定义

  • Table.java
package com.lidong.lowcode.database.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import com.lidong.lowcode.database.constants.database.CharacterSetEnum;
import com.lidong.lowcode.database.constants.database.EngineEnum;
import com.lidong.lowcode.database.constants.enumconst.StrCaseEnum;
import com.lidong.lowcode.database.constants.database.TableOrderEnum;/*** 实体类表注解** @author LiDong* @version 1.0.0* @createTime 9/7/2022 8:39 AM*/
// This annotation is used to Class
@Target(ElementType.TYPE)
// When  run is  effective
@Retention(RetentionPolicy.RUNTIME)
// Java document annotation
@Documented
public @interface Table {/*** 表名** @return String*/String name() default "";/*** 表名大小写** @return StrCaseEnum*/StrCaseEnum tableNameCase() default StrCaseEnum.LOWER;/*** 引擎** @return EngineEnum*/EngineEnum engine() default EngineEnum.INNODB;/*** 自增开始数值** @return int*/int autoIncrementNum() default 0;/*** 字符集** @return CharacterSetEnum*/CharacterSetEnum characterSet() default CharacterSetEnum.UTF_8;/*** 表排序类型** @return TableOrderEnum*/TableOrderEnum orderType() default TableOrderEnum.UTF8_GENERAL_CI;/*** 表备注** @return String*/String comment() default "";
}

扫描自定义注解标志的类

  • Spring ResourceLoader为我们通过资源路径getResource()获取外部资源提供了统一的方法
  • 要获取ResourceLoader的引用,需要实现ResourceLoaderAware接口。
public class LowCodeDataBaseResourceLoader implements ResourceLoaderAware {private static final Logger logger = LoggerFactory.getLogger(LowCodeDataBaseResourceLoader.class);public static final String PATTERN_CLASS = "/**/*.class";/*** 需要扫描的*/private final List<TypeFilter> includeTypeFilterList = new LinkedList<>();/*** 不需要扫描的*/private final List<TypeFilter> excludeTypeFilterList = new LinkedList<>();private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);@Overridepublic void setResourceLoader(ResourceLoader resourceLoader) {resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);}/*** 获取包下面注解标注的类** @param basePackages 包路径 com.lidong.lowcode* @param annotations  需要扫描的注解* @return List*/public static <T> List<Class<T>> getAllClassByAnnotation(String[] basePackages, Class<? extends Annotation>... annotations) {LowCodeDataBaseResourceLoader lowCodeDataBaseResourceLoader = new LowCodeDataBaseResourceLoader();if (!ObjectUtils.isEmpty(annotations)) {for (Class<? extends Annotation> anooationClass : annotations) {lowCodeDataBaseResourceLoader.addIncludeFilter(new AnnotationTypeFilter(anooationClass));}}List<Class<T>> tableClassList = new ArrayList<>();for (String pack : basePackages) {tableClassList.addAll(lowCodeDataBaseResourceLoader.scanPackageGetClassList(pack));}return tableClassList;}/*** 扫描包获取类** @param basePackage 包路径* @param <T>         T* @return List*/public <T> List<Class<T>> scanPackageGetClassList(String basePackage) {List<Class<T>> classes = new ArrayList<>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + org.springframework.util.ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage)) + PATTERN_CLASS;Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);for (Resource resource : resources) {if (resource.isReadable()) {MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);if (matchTypeFilter(metadataReader)) {try {ClassMetadata classMetadata = metadataReader.getClassMetadata();Class<?> aClass = Class.forName(classMetadata.getClassName());classes.add((Class<T>) aClass);} catch (Exception e) {logger.error(e.getMessage(), e);}}}}} catch (Exception e) {throw new InitDataBaseException(e.getMessage(), e);}return classes;}/*** 添加需要扫描的规则** @param includeFilter includeFilter*/private void addIncludeFilter(TypeFilter includeFilter) {includeTypeFilterList.add(includeFilter);}/*** 匹配过滤规则** @param metadataReader metadataReader* @return boolean* @throws IOException exception*/private boolean matchTypeFilter(MetadataReader metadataReader) throws IOException {for (TypeFilter typeFilter : excludeTypeFilterList) {if (typeFilter.match(metadataReader, metadataReaderFactory)) {return false;}}for (TypeFilter typeFilter : includeTypeFilterList) {if (typeFilter.match(metadataReader, metadataReaderFactory)) {return true;}}return false;}
}

InitDataBaseStarter建表启动器

/*** 数据库自动配置启动类** @author LiDong* @version 1.0.0* @createTime 9/9/2022 8:15 PM*/
@Component
@Order(Integer.MIN_VALUE)
public class InitDataBaseStarter implements CommandLineRunner {private static final Logger logger = LoggerFactory.getLogger(InitDataBaseStarter.class);/*** 数据库自动配置建表入口** @param args args* @throws Exception exception*/@Overridepublic final void run(String... args) throws Exception {logger.info("lowcode-database 建表开始...");// 创建数据库建表记录表InitDataBase initDataBase = LowcodeDbSpringContextUtils.getBean(InitDataBase.class);// 创建数据库建表固化表initDataBase.createCuringTable();List<DataBaseTable> dataBaseTableList = initDataBase.scanAnnotationGetTableInfo();logger.info("lowcode-database 共扫描到表 {} 个", dataBaseTableList.size());initDataBase.start(dataBaseTableList);logger.info("lowcode-database 建表结束...");}
}

项目地址

  • https://gitee.com/Marlon_Brando/lowcode_back/tree/develop/lowcode/lowcode-database

http://www.ppmy.cn/news/6488.html

相关文章

[翻译+笔记]变分自编码器:从AutoEncoder到Beta-VAE

与GAN的那篇笔记相同, 做一下笔记. 并不是全文翻译, 只翻译一部分. 原文地址: from AutoEncoder to Beta-VAE 0. 前言 自编码器是用来重构高维数据的&#xff0c;它利用一个有bottleneck层的神经网络。bottleneck层获取压缩的潜在编码&#xff0c;这样将嵌入向量以低维表示可…

Python图像处理【6】通过哈希查找重复和类似的图像

通过哈希查找重复和类似的图像0. 前言1. 哈希函数2. 使用哈希函数查找重复图像3. 使用感知哈希函数查找相似图像3.1 感知哈希函数3.2 查找相似图像4.3 查找指定目录中的相似图像小结系列链接0. 前言 在本节中&#xff0c;我们将讨论图像搜索中的两个相关问题&#xff0c;即使用…

RV1126笔记二十一:车辆颜色识别

若该文为原创文章,转载请注明原文出处。 一、介绍 在学习RV1126的过程中,测试了yolov5可以实现物体检测,物体目标识别等功能,Rock-X也自带了车牌识别功能,具体可以了解下正点原子的资料,里面有详细的介绍,这里介绍一个如何识别车辆颜色。只是提供一个思路,效果不是很…

代码随想录二刷 | day 1

二刷保持手感 数组篇 文章目录二刷保持手感二分查找二分的板子有效的完全平方数x的平方根搜索插入的位置在排序数组中找元素第一个和最后一个位置其余的二分的题我在另一篇有总结27.移除元素977. 有序数组的平方二分查找 二分 二分的板子 二分的板子有两个&#xff0c; de…

2023年【危险化学品生产单位主要负责人】考试及危险化学品生产单位主要负责人考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 危险化学品生产单位主要负责人考试根据新危险化学品生产单位主要负责人考试大纲要求&#xff0c;安全生产模拟考试一点通将危险化学品生产单位主要负责人模拟考试试题进行汇编&#xff0c;组成一套危险化学品生产单位…

python3GUI--音乐播放器(精简版)By:PyQt5(附下载地址)

文章目录一&#xff0e;前言二&#xff0e;预览1.主界面2.歌单页3.歌词页4.播放列表5.mini6.设置三&#xff0e;心得1.解耦2.体验优化3.歌词显示四&#xff0e;总结一&#xff0e;前言 传送门&#xff1a; 1.python3GUI–打造一款音乐播放器By:PyQt5&#xff08;附下载地址&am…

SAP ABAP——SAP简介(三)【S/4 HANA开发环境】

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

Python : 使用python实现教务管理系统(GUI界面+数据库)

一、设计目的 1.熟悉Python和相关软件的操作。 2.基于本学期所学Python知识&#xff0c;熟练应用掌握&#xff0c;制作符合要求的教务管理系统。 3.会对程序运行中的错误代码进行分析&#xff0c;找出合理的解决方案。 4.掌握tkinter开发流程&#xff0c;布局方法和主要组件&a…

WPF开发之Prism详解【内附源码】

在实际应用开发中&#xff0c;随着项目业务逐渐复杂&#xff0c;耦合度会越来越高&#xff0c;维护成本也会直线上升&#xff0c;所以解耦也变得越来越重要。Prism框架为WPF开发中解耦提供了非常便捷的应用。今天主要以一个简单的小例子&#xff0c;简述WPF开发中Prism框架的简…

Linux下JsonCpp的使用教程

文章目录1.Json基础知识2.安装JsonCpp3.jsoncpp的使用1.Json基础知识 ref&#xff1a;Json&#xff0c;Json以及Json在Qt中的使用 【Qt/C/C】 2.安装JsonCpp 开发环境ubuntu sudo apt-get install libjsoncpp-dev3.jsoncpp的使用 jsoncpp 库中的类被定义到了一个 Json 命名…

BUUCTF Misc [ACTF新生赛2020]NTFS数据流 john-in-the-middle [ACTF新生赛2020]swp 喵喵喵

目录 [ACTF新生赛2020]NTFS数据流 john-in-the-middle [ACTF新生赛2020]swp 喵喵喵 [ACTF新生赛2020]NTFS数据流 下载文件 得到500个txt文件&#xff0c;提示了NTFS流隐写&#xff0c;所以使用NtfsStreamsEditor2查看 得到flag flag{AAAds_nntfs_ffunn?} jo…

js获取policy上传到阿里云

<!DOCTYPE html> <html><head><meta charset"utf-8"><title>标准文件上传</title><link rel"stylesheet" href"./lib/viewer/viewer.min.css"><script src"./lib/viewer/viewer.min.js"…

map与set详解

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位大佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 文章目录一、两个概念二、set①set的两种遍历方式②set的erase③set的count三、map①SGI-STL中关于键值对的定义②map的insert③访问键值对④map的op…

node.js+uni计算机毕设项目基于微信小程序订餐系统(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

Spring Authorization Server1.0 介绍与使用

一、版本使用 1、Java&#xff1a;17或者更高的版本。 2、springboot 3.0 3、Spring Authorization Server 1.0版本。 <dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-authorization-server</ar…

【图神经网络】Pytorch图神经网络库——PyG异构图学习

PyG异构图学习举个例子创建异构图Utility函数异构图Transformations创建异构图神经网络自动转换GNN模型使用异构卷积包装器部署现有的异构算子异构图采样参考资料大量真实世界数据集存储为异构图&#xff0c;这促使Pytorch Geometric&#xff08;PyG&#xff09;中引入专门的功…

【大数据系列之JDBC】(八):使用PreparedStatement获取结果集对象

ResultSet 查询需要调用PreparedStatement 的 executeQuery() 方法&#xff0c;查询结果是一个ResultSet 对象 ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集&#xff0c;ResultSet 接口由数据库厂商提供实现 ResultSet 返回的实际上就是一张数据表。有一个指…

spring之反射机制之Spring-DI核心实现

文章目录前言一、回顾反射机制之反射调用方法1、编写一个方法类SomeService2、通过反射机制调用SomeService类中的方法二、反射机制之Spring-DI核心实现前言 调用一个方法当中含有几个要素&#xff1f; 1、调用哪个对象 2、调用哪个方法 3、调用方法的时候传什么参数 4、方法执…

【数列分段DP】膜拜

P1564 膜拜 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意&#xff1a; 思路&#xff1a; 这是个经典模型&#xff1a;数列分段DP&#xff0c;在其他地方也出现过&#xff1a;(150条消息) 代码源每日一题div1 DP 数组划分_lamentropetion的博客-CSDN博客 这类DP模型核…

Redis 性能优化 —— 内存碎片

文章目录一、内存碎片场景描述二、内存碎片概念解析三、内存碎片产生原因四、内存碎片如何判断五、内存碎片解决方案六、内存碎片扩展技能一、内存碎片场景描述 作为内存数据库&#xff0c;内存空间的大小对于 Redis 来说是至关重要的。内存越多意味着存储的数据也会越多&#…
最新文章