前几年不太习惯mybatis自生成sql表的框架,手搓了一个。
项目地址(仅用于学习参考,禁止用于商业,违者必究): auto-sql1.0
项目结构

pom.xml
<dependencies>
<!-- 移除手动管理的 snakeyaml,由 Spring Boot 管理 -->
<!-- Druid 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
<!-- Web 模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 移除版本号,由 parent 管理 -->
</dependency>
<!-- MyBatis-Plus (已包含 MyBatis 功能,无需单独引入 mybatis) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 日志 (由 Spring Boot 管理版本) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 移除 spring-boot-starter-jdbc,使用 Druid 提供的数据源 -->
<!-- BeanUtils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<!-- Apache Commons Lang -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<!-- 升级到兼容版本 -->
<version>3.12.0</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope> <!-- 使用 provided 范围 -->
</dependency>
</dependencies>
配置文件,application.yml加入
auto:
entity:
package: com.excu.entity #实体类包
source:
dbName: ry #数据库名
delPath: c:/ry/old_sql/del_file/ #删除表路径
switchFlag: false #是否驼峰
同级建一个joyce.properties文件
#sql???
auto.def.type.Long=BIGINT
auto.def.length.Long=10
auto.def.type.String=VARCHAR
auto.def.length.String=255
auto.def.type.Integer=INT
auto.def.length.Integer=3
auto.def.type.Date=datetime
auto.def.length.Date=0
auto.def.type.Short=TINYINT
auto.def.length.Short=3
auto.def.type.BigDecimal=DECIMAL
auto.def.length.BigDecimal=10
utils文件夹下的工具类
import java.io.*;
import java.util.Objects;
/**
* @author Xing Dao Rong
* @date 2021/9/3 17:53
* @desc 文件工具类
*/
public class FileUtils implements Serializable {
private static final long serialVersionUID = 6813374997135795261L;
/**
* 创建文件
* @param path
* @return
*/
public static File createFile(String path) {
return createFile(path, false);
}
//新建文件
private static File newFile;
/**
* 创建文件
* @param path
* @param bool 是否使用懒汉模式
* @return
*/
public static File createFile(String path, boolean bool) {
if (!bool) {
newFile = new File(path);
}
if (Objects.isNull(newFile) && bool) {
synchronized (Objects.requireNonNull(newFile)) {
if (Objects.isNull(newFile)) {
newFile = new File(path);
}
}
}
if (!newFile.getParentFile().exists()) {
newFile.mkdirs();
}
return newFile;
}
/**
* 获取文件全路径名称
* @param filePath
* @return
*/
public static String getFilePathName(String filePath) {
String suf = filePath.substring(filePath.indexOf("."));
File file = new File(filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
StringBuilder builder = new StringBuilder();
builder.append(filePath, 0, filePath.indexOf("."));
int index = 0;
while (file.exists()) {
builder.append("(").append(++index).append(")");
String tempPath = builder.toString();
filePath = tempPath + suf;
file = new File(filePath);
}
return filePath;
}
/**
* 写入文件
* @param path
* @param text
*/
public static void writeFile(String path, String text) {
System.out.println("---------->" + path);
File file = createFile(path);
if (!(file.getParentFile()).exists()) {
file.getParentFile().mkdirs();
}
BufferedWriter fw = null;
try {
fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path, false), "UTF-8"));
fw.write(text);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 写入文件
* @param path
* @param text
*/
public static void writeFile(String path, String text, boolean bool) {
newFile = createFile(path, bool);
System.out.println("---------->" + path);
BufferedWriter fw = null;
try {
fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path, bool), "UTF-8"));
fw.write(text);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.excu.utils;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Xing Dao Rong
* @date 2021/9/17 14:00
* @desc 字符串工具类
*/
public class StringUtil extends StringUtils implements Serializable {
private static final long serialVersionUID = 3375173776417938676L;
/**
* 字符串转集合
* @param str
* @return
*/
public static List<String> strToList(String str) {
String[] strs = {};
if (str.contains(",")) {
strs = str.split(",");
} else {
strs = new String[]{str};
}
return Arrays.asList(strs);
}
/**
* 集合转字符串
* @param strs
* @param sym
* @return
*/
public static String listToStr(List<String> strs,String sym) {
return String.join(sym,strs);
}
/**
* 集合是否含有某个字符串
* @param str
* @param list
* @return
*/
public static boolean listIsContainsStr(String str, List<String> list) {
Set<String> set = new HashSet<>(list);
return set.contains(str);
}
/**
* 下划线转驼峰命名
*/
public static String toUnderScoreCase(String str) {
if (str == null) {
return null;
}
if (!str.contains("_")) {
return str;
}
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (i > 0) {
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
} else {
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1)) {
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
sb.append("_");
} else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
sb.append("_");
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 下划线转转驼峰
* @param str
* @return
*/
public static String getUp(String str) {
if (!str.contains("_")) {
return str;
}
Pattern linePattern = Pattern.compile("_(\\w)");
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 驼峰法转下划线
* @param line 源字符串
* @return 转换后的字符串
*/
public static String camelToUnderline(String line,boolean b) {
if (!b){
return line;
}
if (line == null || "".equals(line)) {
return "";
}
char[] chars = line.toCharArray();
int rs = 0;
for (char aChar : chars) {
if (65 <= aChar && aChar <= 90) {
rs = 1;
break;
}
}
if (rs == 0) {
return line;
}
line = String.valueOf(line.charAt(0)).toUpperCase().concat(line.substring(1));
StringBuffer sb = new StringBuffer();
Pattern pattern = Pattern.compile("[A-Z]([a-z\\d]+)?");
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
String word = matcher.group();
sb.append(word.toUpperCase());
sb.append(matcher.end() == line.length() ? "" : "_");
}
return sb.toString().toLowerCase();
}
public static String changeType(String str) {
Matcher mat = Pattern.compile("(?<=\\()(\\S+)(?=\\))").matcher(str);//此处是中文输入的()
while (mat.find()) {
str = str.replace("(" + mat.group() + ")", "");
}
return str;
}
/**
* 获取实体类
* @param str
* @return
*/
public static String getClass(String str) {
str = getUp(str);
String[] var1 = {"bigint", "varchar", "datetime", "char", "int", "double"};
String[] var2 = {"Long", "String", "Date", "String", "Integer", "Double"};
for (int i = 0; i < var1.length; i++) {
str = str.replace(var1[i], var2[i]);
}
str = changeType(str).replace("/;", "/\n");
return str;
}
/**
* 获取名字
* @param tableName
* @return
*/
public static String getClassName(String tableName) {
return getUp(tableName).substring(0, 1).toUpperCase() + getUp(tableName).substring(1);
}
/**
* 转换类型
* @param type
* @return
*/
public static String changeType2(String type) {
String[] var1 = {"bigint", "varchar", "datetime", "char", "int", "text", "decimal", "date", "tinyint"};
String[] var2 = {"Long", "String", "Date", "String", "Integer", "String", "BigDecimal", "Date", "Integer"};
for (int i = 0; i < var1.length; i++) {
if (type.equals(var1[i])) {
return var2[i];
}
}
return "String";
}
/**
* 拼接字符
* @param prefix
* @param strs
* @param suffix
* @param g
* @return
*/
public static String appendStr(String prefix, List<String> strs, String suffix, String g) {
StringBuilder stringBuilder = new StringBuilder();
StringBuilder prefixBuilder = stringBuilder.append(prefix);
if (strs.isEmpty()) {
return prefixBuilder.append(suffix).toString();
}
for (int i = 0; i < strs.size(); i++) {
if (StringUtils.isNoneEmpty(strs.get(i))) {
prefixBuilder.append(strs.get(i));
}
if (StringUtils.isNoneEmpty(g) && i != strs.size() - 1) {
prefixBuilder.append(g);
}
}
return prefixBuilder.append(suffix).toString();
}
/**
* 字符匹配多个
* @param strs
* @return
*/
public static boolean equalsIgnoreCase(String... strs) {
boolean flag = false;
for (int i = 1; i < strs.length; i++) {
if (strs[0].equalsIgnoreCase(strs[i])) {
flag = true;
break;
}
}
return flag;
}
/**
* 加密
* @param password
* @return
*/
public static String encryptionPassword(String password) {
int len = password.length();
char[] chars = password.toCharArray();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
char condiment = (char) ((len - i) % 7);
if (len % 2 == 0) {
builder.append(chars[i]).append(condiment);
} else {
builder.append(condiment).append(chars[i]);
}
}
return builder.toString();
}
/**
* 解密
* @param password
* @return
*/
public static String decryptPassword(String password) {
int len = password.length() / 2;
char[] chars = password.toCharArray();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (len % 2 == 0) {
if (i % 2 == 0) {
builder.append(chars[i]);
}
} else {
if (i % 2 == 1) {
builder.append(chars[i]);
}
}
}
return builder.toString();
}
}
entity 文件下的文件
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @Author: XingDaoRong
* @Date: 2021/11/18
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Column implements Serializable{
/**
* 表字段名称
*/
private String columnName;
/**
* 最大长度
*/
private Long columnLength;
/**
* 是否为空
*/
private String isNull;
/**
* 是否为主键
*/
private String isKey;
/**
* 默认值
*/
private String defaultValue;
/**
* 表字段类型
*/
private String columnType;
/**
* 表字段注释
*/
private String columnComment;
/**
* 表名字
*/
private String tableName;
/**
* 表注释
*/
private String tableComment;
/**
* 增长
*/
private String autoIncrement;
}
mapper文件下的文件
import com.excu.entity.Column;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public interface ColumnsMapper extends BaseMapper<Column> {
// 用@SelectProvider指定SQL提供类和方法
@SelectProvider(type = ColumnsSqlProvider.class, method = "getColumnsSql")
List<Column> getColumns(@Param("tableName") String tableName, @Param("dbName") String dbName);
@SelectProvider(type = ColumnsSqlProvider.class, method = "getOneSql")
Column getOne(@Param("tableName") String tableName, @Param("dbName") String dbName);
@Select("SELECT table_name AS tableName, " +
"table_comment AS tableComment " +
"FROM INFORMATION_SCHEMA.TABLES " +
"WHERE table_schema = #{databaseName}")
List<Column> getAllTables(@Param("databaseName") String databaseName);
@SelectProvider(type = ColumnsSqlProvider.class, method = "getMapDataSql")
List<Map<String, Object>> getMapData(@Param("dbName") String dbName,
@Param("tableName") String tableName,
@Param("offset") Integer offset,
@Param("pageNumber") Integer pageNumber);
@Select("SELECT count(*) FROM ${dbName}.${tableName}")
Integer getCount(@Param("dbName") String dbName, @Param("tableName") String tableName);
@Select("SELECT DISTINCT a.column_name AS columnName, " +
"a.column_comment AS columnComment, " +
"a.data_type AS columnType, " +
"a.IS_NULLABLE AS isNull, " +
"a.COLUMN_KEY AS isKey, " +
"a.COLUMN_DEFAULT AS defaultValue, " +
"a.table_name AS tableName, " +
"a.CHARACTER_MAXIMUM_LENGTH AS columnLength, " +
"b.table_comment AS tableComment, " +
"b.AUTO_INCREMENT AS autoIncrement " +
"FROM information_schema.columns a " +
"RIGHT JOIN information_schema.tables b " +
"ON a.table_name = b.table_name " +
"WHERE b.table_schema = #{dbName}")
List<Column> getAllTables2(@Param("dbName") String dbName);
// 定义SQL提供类,内部用Java代码拼接动态SQL
class ColumnsSqlProvider {
// 对应getColumns方法的动态SQL
public String getColumnsSql(@Param("tableName") String tableName, @Param("dbName") String dbName) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT DISTINCT a.column_name AS columnName, ");
sql.append("a.column_comment AS columnComment, ");
sql.append("a.data_type AS columnType, ");
sql.append("a.IS_NULLABLE AS isNull, ");
sql.append("a.COLUMN_KEY AS isKey, ");
sql.append("a.COLUMN_DEFAULT AS defaultValue, ");
sql.append("a.table_name AS tableName, ");
sql.append("a.CHARACTER_MAXIMUM_LENGTH AS columnLength, ");
sql.append("b.table_comment AS tableComment, ");
sql.append("b.AUTO_INCREMENT AS autoIncrement ");
sql.append("FROM information_schema.columns a ");
sql.append("RIGHT JOIN information_schema.tables b ");
sql.append("ON a.table_name = b.table_name ");
sql.append("WHERE a.table_name = #{tableName} ");
// 替代<if test="dbName != null and dbName != ''">
if (dbName != null && !dbName.trim().isEmpty()) {
sql.append("AND b.table_schema = #{dbName} ");
}
return sql.toString();
}
// 对应getOne方法的动态SQL
public String getOneSql(@Param("tableName") String tableName, @Param("dbName") String dbName) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT table_name AS tableName, ");
sql.append("table_comment AS tableComment ");
sql.append("FROM INFORMATION_SCHEMA.TABLES ");
sql.append("WHERE TABLE_NAME = #{tableName} ");
if (dbName != null && !dbName.trim().isEmpty()) {
sql.append("AND table_schema = #{dbName} ");
}
return sql.toString();
}
// 对应getMapData方法的动态SQL
public String getMapDataSql(@Param("dbName") String dbName,
@Param("tableName") String tableName,
@Param("offset") Integer offset,
@Param("pageNumber") Integer pageNumber) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT * FROM ${dbName}.${tableName} ");
// 替代<if test="offset != null and pageNumber != null and pageNumber != 0">
if (offset != null && pageNumber != null && pageNumber != 0) {
sql.append("LIMIT #{offset}, #{pageNumber} ");
}
return sql.toString();
}
}
}
service
import com.excu.entity.Column;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface ColumnsService {
/**
* 获取所有列
* @param tableName
* @param dbName
* @return
*/
List<Column> getColumns(String tableName, String dbName);
/**
* 获得表名和注释
* @param tableName
* @param dbName
* @return
*/
Column getTable(String tableName, String dbName);
/**
* 自动创建表sql
* @param list
*/
void execute(List<String> list);
/**
* 查询表数据
* @param tableName
* @return
*/
List<Map<String,Object>> getMapTableData(String tableName,String dbName,int pageNumber,int offset);
/**
* 根据set获取表信息
* @param tableSet
* @param dbName
* @return
*/
Map<String, List<Column>> getTableInfoBySet(Set<String> tableSet, String dbName);
}
impl
import com.excu.entity.Column;
import com.excu.mapper.ColumnsMapper;
import com.excu.service.ColumnsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* @Author: XingDaoRong
* @Date: 2021/11/19
*/
@Service
public class ColumnsServiceImpl implements ColumnsService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private ColumnsMapper columnsMapper;
@Override
public List<Column> getColumns(String tableName, String dbName) {
//为了提高效率,先检测数据库和数据表
Column table = columnsMapper.getOne(tableName, dbName);
if (Objects.isNull(table)){
return null;
}
List<Column> columns = columnsMapper.getColumns(tableName, dbName);
List<Column> list = new ArrayList<>();
for (Column column : columns) {
if (Objects.isNull(column.getColumnLength())){
column.setColumnLength(0L);
}
list.add(column);
}
return list;
}
@Override
public Column getTable(String tableName, String dbName) {
return columnsMapper.getOne(tableName, dbName);
}
@Override
public void execute(List<String> sqls) {
for (String sql : sqls) {
jdbcTemplate.execute(sql);
}
}
@Override
public List<Map<String,Object>> getMapTableData(String tableName,String dbName,int pageNumber,int offset) {
return columnsMapper.getMapData(tableName, dbName,pageNumber,offset);
}
@Override
public Map<String, List<Column>> getTableInfoBySet(Set<String> tableSet,String dbName) {
Map<String, List<Column>> map = new HashMap<>();
for (String tableName : tableSet) {
List<Column> columns = getColumns(tableName, dbName);
if (Objects.nonNull(columns)&&!columns.isEmpty()){
map.put(tableName,columns);
}
}
return map;
}
}
factory文件下文件有点多
demo
import com.excu.factory.demo.base.BaseFactory;
import com.excu.factory.entity.annotation.auto.Column;
import com.excu.factory.entity.annotation.auto.Ids;
import com.excu.factory.entity.annotation.auto.NotExist;
import com.excu.factory.entity.annotation.auto.Table;
import com.excu.factory.entity.auto.ColumnEntity;
import com.excu.factory.entity.auto.TableEntity;
import com.excu.factory.enums.TableStrategy;
import com.excu.factory.init.AutoCreateTableInit;
import com.excu.factory.inter.TableFactory;
import com.excu.utils.FileUtils;
import com.excu.utils.StringUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* @author: Joyce
* @autograph: Logic is justice
* @date: 2022/05/13-- 21:48
* @describe: 自动创建表工厂_扫描所有相关类
*/
public class AutoCreateTableFactory extends BaseFactory implements TableFactory {
//日志
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//sql容器
private static Map<TableEntity, List<ColumnEntity>> map = null;
//计数标志
private static int idValue = 0;
//检测子文件容器
private static Set<String> tableNameSet = null;
private static Map<String,Set<String>> exitMap = null;
//sql容器
private static List<String> sqls = null;
//工厂对象
private static AutoCreateTableFactory autoCreateTableFactory = null;
//配置信息的容器
private static Map<String, ColumnEntity> defMap = null;
//是否开启驼峰
private static boolean switchFlag = true;
/**
* 获取实例
* @return
*/
public static AutoCreateTableFactory getInstance(boolean b){
//是否开属性启驼峰
switchFlag = b;
if (Objects.isNull(autoCreateTableFactory)) {
autoCreateTableFactory = new AutoCreateTableFactory();
}
return autoCreateTableFactory;
}
/**
* 获取名称集合
* @return
*/
public Map<String,Set<String>> getTableSet(){
return exitMap;
}
/**
* 工厂初始化
* @param ps
* @return
*/
private void init(String ps) {
AutoCreateTableFactory instance = getInstance(switchFlag);
if (Objects.isNull(map) && Objects.isNull(tableNameSet) && Objects.isNull(sqls) && Objects.isNull(defMap)) {
//初始化
map = new ConcurrentHashMap<>();
tableNameSet = new HashSet<>();
sqls = new ArrayList<>();
exitMap = new HashMap<>();
try {
//读取配置
InputStream in = getClassLoader().getResourceAsStream("joyce.properties");
defMap = AutoCreateTableInit.readDefConfig(in);
if (in!=null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//扫描包
instance.scannerPackage(ps);
initExitMap();
}
}
/**
* 初始化传出的类型
*/
private void initExitMap(){
Set<String> exitSet = new HashSet<>();
Set<String> delSet = new HashSet<>();
for (Map.Entry<TableEntity, List<ColumnEntity>> entry : map.entrySet()) {
if (entry.getKey().getStrategy().equals(TableStrategy.ADD.getCode().toString())){
logger.info("***add:{}",entry.getKey());
exitSet.add(entry.getKey().getName());
}
if (entry.getKey().getStrategy().equals(TableStrategy.FORCE.getCode().toString())){
logger.info("***del:{}",entry.getKey());
delSet.add(entry.getKey().getName());
}
}
exitMap.put(TableStrategy.ADD.getCode().toString(),exitSet);
exitMap.put(TableStrategy.FORCE.getCode().toString(),delSet);
}
/**
* 扫描指定文件
* @param packagePath
*/
private void scannerPackage(String packagePath) {
String[] packages;
if (packagePath.contains(";")) {
packages = StringUtil.split(packagePath, ";");
} else {
packages = new String[]{packagePath};
}
//检测文件是否有包含关系
checkIsParentFile(packages);
for (String aPackage : packages) {
try {
scanner(aPackage);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 检测里面是否有子文件
* @param packages
*/
private void checkIsParentFile(String[] packages) {
Set<String> set = Arrays.stream(packages).collect(Collectors.toSet());
if (set.contains(null) || set.contains("")) {
throw new NullPointerException("配置包不可含有null或者''");
}
if (packages.length < 2) {
return;
}
for (int i = 0; i < packages.length; i++) {
logger.info("正在扫描包:{}",packages[i]);
File f1 = getFile(packages[i]);
for (int j = i + 1; j < packages.length; j++) {
File f2 = getFile(packages[j]);
if (f1.equals(f2.getParentFile()) || f2.equals(f1.getParentFile())) {
throw new RuntimeException(packages[i] + "与" + packages[j] + "是相互包含的关系,必须选择一个");
}
}
}
}
/**
* 扫描指定文件并且填充属性
* @param entityClassPackage
* @throws ClassNotFoundException
*/
private void scanner(String entityClassPackage) {
File dir = getFile(entityClassPackage);
ClassLoader classLoader = getClassLoader();
try {
fillMap(dir, classLoader);
} catch (ClassNotFoundException | InvocationTargetException | IllegalAccessException | NoSuchMethodException | InstantiationException e) {
e.printStackTrace();
}
}
/**
* 填充属性
* @param dir
* @param classLoader
* @throws ClassNotFoundException
*/
private void fillMap(File dir, ClassLoader classLoader) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
File[] files = dir.listFiles();
if (files!=null){
for (File file : files) {
fillMapByFile(file, classLoader);
if (file.isDirectory()) {
fillMap(file, classLoader);
}
}
}
}
/**
* 通过文件对map填充
* @param file
* @param classLoader
*/
private void fillMapByFile(File file, ClassLoader classLoader) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
if (file.isFile()) {
String filePath = file.getAbsolutePath();
if (!filePath.endsWith(".class")) {
return;
}
Class<?> loadClass = loadClassByPath(filePath, classLoader, "com", "class");
if (loadClass.isAnnotationPresent(Table.class)) {
//类注解获取并且填充
Table table = loadClass.getAnnotation(Table.class);
if (table.isParent()) {
logger.warn(loadClass + "为被继承类,无法扫描到map容器中");
return;
}
TableEntity tableEntity = new TableEntity();
setTableEntity(table,tableEntity,loadClass);
//属性注解获取并且填充
Field[] fields = getFieldsByAutoCreate(loadClass);
//储存属性的容器
List<ColumnEntity> list = new ArrayList<>();
List<Field> idsField = new ArrayList<>();
for (Field field : fields) {
//检测上是否有无关数据库的属性字段注解
NotExist notExist = field.getAnnotation(NotExist.class);
if (Objects.nonNull(notExist)) {
if (notExist.require()) {
continue;
}
}
//检测列属性字段注解并且填充
Column column = field.getAnnotation(Column.class);
if (Objects.nonNull(column)) {
if (!column.exist()) {
continue;
}
}
if (Objects.nonNull(column)) {
ColumnEntity columnEntity = new ColumnEntity();
if (StringUtil.isBlank(column.name())){
columnEntity.setName(StringUtil.toUnderScoreCase(field.getName()));
}
createColumnByColumnAn(columnEntity, column);
list.add(AutoCreateTableInit.columnConfigRules(columnEntity));
} else {
idsField.add(field);
}
}
//检测是否有ids注解是否存在
boolean rs = isHaveIds(fields);
if (rs) {
List<ColumnEntity> tableEntityList = getTableEntitySuperList(fields, idsField);
list.addAll(tableEntityList);
}
List<ColumnEntity> newList = new ArrayList<>();
if (!list.isEmpty()){
for (ColumnEntity columnEntity : list) {
if (Objects.isNull(columnEntity)) {
continue;
}
ColumnEntity newColumnEntity = (ColumnEntity) BeanUtils.cloneBean(columnEntity);
newList.add(newColumnEntity);
}
}
List<ColumnEntity> columnEntities = checkRepeatColumnEntity(newList);
if (Objects.nonNull(columnEntities)) {
throw new RuntimeException("存在如下相同属性,无法创建:" + columnEntities);
}
map.put(tableEntity, newList);
}
}
}
/**
* 设置属性
* @param table
* @param tableEntity
* @param loadClass
* @return
*/
private void setTableEntity(Table table, TableEntity tableEntity, Class<?> loadClass){
if (StringUtil.isNoneBlank(table.name())){
tableEntity.setName(table.name());
}else {
tableEntity.setName(StringUtil.camelToUnderline(loadClass.getSimpleName(),switchFlag));
}
tableEntity.setContent(table.content());
tableEntity.setStrategy(table.strategy().getCode().toString());
tableEntity = AutoCreateTableInit.tableEntityConfigRules(tableEntity);
//检查是否有重复注解
checkRepeatTableName(tableEntity.getName());
}
/**
* 获取父类属性实体类集合
* @param fields
* @param idsField
* @return
*/
private List<ColumnEntity> getTableEntitySuperList(Field[] fields, List<Field> idsField) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
++idValue;
List<ColumnEntity> columnEntities = new ArrayList<>();
Set<String> values = checkKey(fields, "values");
Set<String> uniques = checkKey(fields, "uniques");
for (Field field : idsField) {
ColumnEntity columnEntity = createColumnByIdsAn(field);
if (Objects.nonNull(columnEntity)) {
ColumnEntity newColumnEntity = (ColumnEntity) BeanUtils.cloneBean(columnEntity);
if (values.contains(columnEntity.getName())) {
newColumnEntity.setComment("主键");
newColumnEntity.setKey(true);
newColumnEntity.setNotNull(true);
}
if (uniques.contains(columnEntity.getName())) {
newColumnEntity.setUnique(true);
} else {
newColumnEntity.setUnique(false);
}
newColumnEntity.setIdValue(idValue);
columnEntities.add(AutoCreateTableInit.columnConfigRules(newColumnEntity));
}
}
return columnEntities;
}
/**
* 返回ids注解集合
* @param fields
* @return
*/
private Set<String> checkKey(Field[] fields, String type) {
Set<String> keyList = new HashSet<>();
String[] keys = {};
//Ids注解计数器
for (Field field : fields) {
Ids ids = field.getAnnotation(Ids.class);
if (Objects.nonNull(ids)) {
if ("values".equals(type)) {
keys = ids.values();
}
if ("uniques".equals(type)) {
keys = ids.uniques();
}
}
if (keys.length != 0) {
break;
}
}
if (keys.length == 0) {
return keyList;
}
//检测Ids中的属性是否有重复元素,有的话也会报错
if (Arrays.stream(keys).collect(Collectors.toSet()).size() != keys.length) {
throw new RuntimeException("注解Ids."+type+"中存在相同属性");
}
for (String key : keys) {
for (Field field : fields) {
if (key.equals(field.getName())) {
keyList.add(key);
}
}
}
return keyList;
}
/**
* 检测list中重复元素
* @param list
* @return
*/
private List<ColumnEntity> checkRepeatColumnEntity(List<ColumnEntity> list) {
if (Objects.isNull(list)) {
return null;
}
if (list.isEmpty()) {
return null;
}
if (new HashSet<>(list).size() == list.size()) {
return null;
}
List<ColumnEntity> columnEntities = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
int index = i + 1;
while (index < list.size()) {
if (list.get(i).equals(list.get(index))) {
columnEntities.add(list.get(i));
index++;
}
}
}
if (!columnEntities.isEmpty()) {
return columnEntities;
}
return null;
}
/**
* 根据column注解创建实体类
* @param columnEntity
* @param column
*/
private void createColumnByColumnAn(ColumnEntity columnEntity, Column column) {
columnEntity.setAuto(column.auto());
columnEntity.setComment(column.comment());
columnEntity.setKey(column.isKey());
if (StringUtil.isNoneBlank(column.name())){
columnEntity.setName(column.name());
}
columnEntity.setLength(Long.valueOf(column.length()));
columnEntity.setType(column.type().getStr());
columnEntity.setNotNull(column.isNotNull());
columnEntity.setDefaultValue(column.defaultValue());
columnEntity.setUnique(column.unique());
columnEntity.setDecimal(column.decimal());
if (columnEntity.getAuto()) {
columnEntity.setKey(true);
}
if (column.isKey()) {
columnEntity.setNotNull(true);
}
}
/**
* 根据ids注解创建实体类
* @param field
* @return
*/
private ColumnEntity createColumnByIdsAn(Field field) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
String name = StringUtil.toUnderScoreCase(field.getName());
String type = field.getType().toString();
type = type.substring(type.lastIndexOf(".") + 1);
boolean rs = defMap.containsKey(type);
if (rs) {
ColumnEntity columnEntity = (ColumnEntity) BeanUtils.cloneBean(defMap.get(type));
columnEntity.setName(name);
return (ColumnEntity) BeanUtils.cloneBean(columnEntity);
}
return null;
}
/**
* 判断是否有ids
* @param fields
* @return
*/
private boolean isHaveIds(Field[] fields) {
for (Field field : fields) {
Ids ids = field.getAnnotation(Ids.class);
if (Objects.nonNull(ids)) {
return true;
}
}
return false;
}
/**
* 检测是否已存在
* @param key
* @return
*/
private void checkRepeatTableName(String key) {
if (tableNameSet.contains(key)) {
throw new RuntimeException("实体类表名'" + key + "'已注册,无法重复创建");
}
tableNameSet.add(key);
}
/**
* 根据路径获取对应文件
* @param packagePath
* @return
*/
private File getFile(String packagePath) {
ClassLoader classLoader = getClassLoader();
String rePackageName = packagePath.replace(".", "/");
URL resource = classLoader.getResource(rePackageName);
return new File(resource.getFile());
}
/**
* 根据路径获取加载
*/
private ClassLoader getClassLoader() {
return AutoCreateTableFactory.class.getClassLoader();
}
/**
* 填充sqls
* @param maps
*/
private void fillSqls(Map<String,List<com.excu.entity.Column> > maps) {
for (Map.Entry<TableEntity, List<ColumnEntity>> entry : map.entrySet()) {
List<com.excu.entity.Column> existColumns = null;
if (maps.containsKey(entry.getKey().getName())){
existColumns = maps.get(entry.getKey().getName());
}
String[] sqlStrArr = selectCreateSql(entry.getKey(), entry.getValue(), existColumns);
if (Objects.isNull(sqlStrArr)) {
continue;
}
for (String sql : sqlStrArr) {
if (StringUtil.isBlank(sql)){
continue;
}
sqls.add(sql);
}
}
}
/**
* 自动选取策略创建
* @param tableEntity
* @param columnEntities
* @return
*/
private String[] selectCreateSql(TableEntity tableEntity, List<ColumnEntity> columnEntities, List<com.excu.entity.Column> existColumns) {
String strategy = tableEntity.getStrategy();
switch (strategy) {
case "1":
if (Objects.isNull(existColumns)){
return new String[]{createTableSql(tableEntity, columnEntities)};
}
if (existColumns.isEmpty()){
logger.warn("{}表无存在旧字段,将策略自动转向安全创建",tableEntity.getName());
return new String[]{createTableSql(tableEntity, columnEntities)};
}
/* String[] strings = modifyTable(tableEntity, columnEntities, existColumns);
if (Objects.isNull(strings)){
return new String[]{alterTable(tableEntity, columnEntities, existColumns)};
}
strings[strings.length-1] = alterTable(tableEntity, columnEntities, existColumns);
return strings;*/
return new String[]{alterTable(tableEntity, columnEntities, existColumns)};
case "2":
return new String[]{createTableSql(tableEntity, columnEntities)};
case "3":
return new String[]{deleteTable(tableEntity.getName()), createTableSql(tableEntity, columnEntities)};
default:
return null;
}
}
/**
* 创建表的sql
* @param tableEntity
* @param columnEntities
* @return
*/
private String createTableSql(TableEntity tableEntity, List<ColumnEntity> columnEntities) {
int isHaveKey = 0;
if (Objects.isNull(columnEntities) || columnEntities.isEmpty()) {
throw new RuntimeException("在创建" + tableEntity.getName() + "的时候,该类无属性类,因此无法创建");
}
StringBuilder sb = new StringBuilder();
sb.append("create table ");
sb.append(" if not exists ");
sb.append(tableEntity.getName())
.append("(");
for (int i = 0; i < columnEntities.size(); i++) {
if (Objects.isNull(columnEntities.get(i))) {
continue;
}
if (Objects.isNull(columnEntities.get(i).getName())) {
continue;
}
ColumnEntity column = columnEntities.get(i);
if (Objects.isNull(column)) {
continue;
}
sb.append("`")
.append(StringUtil.camelToUnderline(column.getName(),switchFlag))
.append("` ")
.append(column.getType())
.append("(")
.append(column.getLength());
if (column.getDecimal()!=null){
if (column.getDecimal()!=-1){
sb.append(",").append(column.getDecimal());
}
}
sb.append(") ");
if (column.getNotNull()) {
sb.append(" not null ");
}
if (column.getUnique()) {
sb.append(" unique ");
}
String defVal = column.getDefaultValue();
if (!column.getKey() && (!column.getNotNull() || !"NULL".equalsIgnoreCase(defVal))) {
sb.append(" default ").append(defVal);
}
if (column.getAuto()) {
sb.append(" auto_increment ");
}
if (column.getKey()) {
sb.append(" primary key ");
isHaveKey = 1;
}
if (StringUtil.isNoneBlank(column.getComment())) {
sb.append(" comment '")
.append(column.getComment())
.append("'");
}
sb.append(",");
}
StringBuilder newSb = new StringBuilder();
newSb.append(sb.substring(0, sb.length() - 1));
newSb.append(")ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_general_ci");
if (Objects.nonNull(tableEntity.getContent())) {
newSb.append(" COMMENT = '").append(tableEntity.getContent()).append("'");
}
newSb.append(" ROW_FORMAT = Dynamic");
if (isHaveKey==0){
System.out.println(tableEntity.getName()+"类创建时,未发现主键");
}
return newSb.toString();
}
/**
* 给表添加字段
* @param tableEntity
* @param columnEntities
* @return
*/
private String alterTable(TableEntity tableEntity, List<ColumnEntity> columnEntities, List<com.excu.entity.Column> existColumns) {
List<String> list = existColumns.stream().map(com.excu.entity.Column::getColumnName).collect(Collectors.toList());
List<ColumnEntity> differentList = getDifferentList(list, columnEntities);
if (!differentList.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append("alter table ").append(tableEntity.getName()).append(" add (");
for (int i = 0; i < differentList.size(); i++) {
if (Objects.isNull(differentList.get(i))) {
continue;
}
if (Objects.isNull(differentList.get(i).getName())) {
continue;
}
ColumnEntity column = differentList.get(i);
if (Objects.isNull(column)) {
continue;
}
sb.append("`")
.append(StringUtil.camelToUnderline(column.getName(),switchFlag))
.append("` ")
.append(column.getType())
.append("(")
.append(column.getLength());
if (getDecimal().contains(column.getType())){
sb.append(",").append(column.getDecimal());
}
sb.append(") ");
if (column.getNotNull()) {
sb.append(" not null ");
}
if (column.getUnique()) {
sb.append(" unique ");
}
String defVal = column.getDefaultValue();
if (!column.getKey() && (!column.getNotNull() || !defVal.equalsIgnoreCase("NULL"))) {
sb.append(" default ").append(defVal);
}
if (column.getAuto()) {
sb.append(" auto_increment ");
}
if (column.getKey()) {
sb.append(" primary key ");
}
if (StringUtil.isNoneBlank(column.getComment())) {
sb.append(" comment '")
.append(column.getComment())
.append("'");
}
sb.append(",");
}
StringBuilder newSb = new StringBuilder();
newSb.append(sb.substring(0, sb.length() - 1));
return newSb.append(")").toString();
}
return null;
}
private static Set<String> getDecimal(){
HashSet<String> set1 = new HashSet<>();
set1.add("DOUBLE");
set1.add("DECIMAL");
return set1;
}
/**
* 修改属性
* @param tableEntity
* @param columnEntities
* @param existColumns
* @return
*/
private String[] modifyTable(TableEntity tableEntity, List<ColumnEntity> columnEntities, List<com.excu.entity.Column> existColumns){
List<String> list = new ArrayList<>();
List<ColumnEntity> cbfd = getCommonButFileDifferentList(columnEntities, existColumns);
if (!cbfd.isEmpty()) {
for (int i = 0; i < cbfd.size(); i++) {
StringBuilder sb = new StringBuilder();
sb.append("alter table ").append(tableEntity.getName()).append(" modify ");
if (Objects.isNull(cbfd.get(i))) {
continue;
}
if (Objects.isNull(cbfd.get(i).getName())) {
continue;
}
ColumnEntity column = cbfd.get(i);
if (Objects.isNull(column)) {
continue;
}
sb.append("`")
.append(StringUtil.camelToUnderline(column.getName(),switchFlag))
.append("` ")
.append(column.getType())
.append("(")
.append(column.getLength())
.append(") ");
if (column.getNotNull()) {
sb.append(" not null ");
}
if (column.getUnique()) {
sb.append(" unique ");
}
String defVal = column.getDefaultValue();
if (!column.getKey() && (!column.getNotNull() || !defVal.equalsIgnoreCase("NULL"))) {
sb.append(" default ").append(defVal);
}
if (StringUtil.isNoneBlank(column.getComment())) {
sb.append(" comment '")
.append(column.getComment())
.append("'");
}
list.add(sb.toString());
}
return list.toArray(new String[list.size()+1]);
}
return null;
}
/**
* 删除表
* @param tableName
* @return
*/
private String deleteTable(String tableName) {
return "DROP TABLE IF EXISTS `" + tableName + "`";
}
/**
* 获取工程名称
* @return
*/
@Override
public String getTableFactoryName() {
return "自动创建sql表工厂";
}
/**
* 检测是否有多出的字段
* @param strs
* @param list
* @return
*/
private List<ColumnEntity> getDifferentList(List<String> strs, List<ColumnEntity> list) {
List<ColumnEntity> columnEntities = new ArrayList<>();
for (ColumnEntity columnEntity : list) {
boolean rs = StringUtil.listIsContainsStr(StringUtil.camelToUnderline(columnEntity.getName(),switchFlag), strs);
if (!rs) {
columnEntities.add(columnEntity);
}
}
return columnEntities;
}
/**
* 检测是否有字段需要修改属性
* @param columnEntities
* @param list
* @return
*/
private List<ColumnEntity> getCommonButFileDifferentList(List<ColumnEntity> columnEntities,List<com.excu.entity.Column> list){
List<ColumnEntity> columnEntityList = new ArrayList<>();
for (com.excu.entity.Column entity : list) {
ColumnEntity columnEntity = new ColumnEntity();
columnEntity.columnToColumnEntity(entity);
columnEntityList.add(columnEntity);
}
List<ColumnEntity> entities = new ArrayList<>();
for (ColumnEntity columnEntity : columnEntityList) {
for (ColumnEntity entity : columnEntities) {
if (entity.getName().equals(columnEntity.getName())){
if (!columnEntity.equals(entity)){
entities.add(entity);
}
}
}
}
return entities;
}
/**
* 获取执行sql集合
* @param maps
* @return
*/
@Override
public List<String> getSqls(Map<String ,List<com.excu.entity.Column>> maps) {
try {
//填充属性
fillSqls(maps);
} catch (Exception e) {
e.printStackTrace();
}
sqls.removeIf(Objects::isNull);
sqls.forEach(sql -> logger.info("生成sql:------->" + sql));
return sqls;
}
@Override
public void initData(String ps) {
if (StringUtil.isBlank(ps)) {
logger.error("扫描包路径格式不合法,若服务器可无视");
}
init(ps);
}
/**
* 导出文件
* @param columns
* @param mapTableData
*/
public void exportSqlFile(List<com.excu.entity.Column> columns, List<Map<String, Object>> mapTableData, com.excu.entity.Column column, String path) {
TableEntity tableEntity = new TableEntity();
tableEntity.columnToTableEntity(column);
List<ColumnEntity> columnEntities = new ArrayList<>();
for (com.excu.entity.Column c : columns) {
ColumnEntity columnEntity = new ColumnEntity();
columnEntity.columnToColumnEntity(c);
logger.info("---------->{}",columnEntity);
AutoCreateTableInit.columnConfigRules(columnEntity);
columnEntities.add(columnEntity);
}
String tableSql = createTableSql(tableEntity, columnEntities)+"\n";
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(tableSql);
for (Map<String, Object> maps : mapTableData) {
stringBuilder.append("INSERT INTO ").append(tableEntity.getName()).append("(");
stringBuilder.append(mapToStr(maps, "k", columnEntities)).append(") VALUES(");
stringBuilder.append(mapToStr(maps, "v", columnEntities)).append(")\n");
}
String filePathName = FileUtils.getFilePathName(path + tableEntity.getName() + ".sql");
FileUtils.writeFile(filePathName,stringBuilder.toString());
logger.info("删除的旧文件sql文件:{}",filePathName);
}
/**
* map中的数据转成sql文件
* @param map
* @param kv
* @param columnEntities
* @return
*/
private String mapToStr(Map<String,Object> map,String kv, List<ColumnEntity> columnEntities){
StringBuilder builder = new StringBuilder();
int index = 0;
if ("k".equals(kv)){
for (String k : map.keySet()) {
builder.append(k);
if (index++ < map.keySet().size()){
builder.append(",");
}
}
}
if ("v".equals(kv)){
for (Object value : map.values()) {
logger.info("------------>{}",columnEntities.get(index).getType());
if (StringUtil.equalsIgnoreCase(columnEntities.get(index).getType(),"varchar","text","char","datetime")||Objects.isNull(columnEntities.get(index).getType())){
builder.append("'")
.append(value)
.append("'");
}else {
builder.append(value);
}
if (index++ < map.keySet().size()){
builder.append(",");
}
}
}
return builder.toString();
}
}
base
import com.excu.factory.entity.annotation.auto.Table;
import com.excu.utils.StringUtil;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author: Joyce
* @autograph: Logic is justice
* @date: 2022/09/05-- 15:08
* @describe:
*/
public class BaseFactory {
//类型信息
protected Object[] typeName = {
"byte","Byte",0,
"String","String","",
"short","Short",0,
"int","Integer",0,
"long","Long",0L,
"float","Float",0.0f,
"double","Double",0.0,
"boolean","Boolean",false,
"char","Character",0};
//下标基准
private static final int INDEX = 1;
protected static final String defParent ="com";
protected static final String fileType ="class";
/**
* 获取类型的初始值
* @param type
* @return
*/
protected Object getTypeValue(String type){
Object o = null;
for (int i = 0; i < typeName.length; i++) {
if ((i+ INDEX)%3 == 0){
if (type.contains(String.valueOf(typeName[i-1])) || type.contains(String.valueOf(typeName[i-2]))){
o = typeName[i];
break;
}
}
}
return o;
}
/**
* 获取所有类型
* @return
*/
protected Set<String> getAllTypes(){
Set<String> set = new HashSet<>();
for (int i = 0; i < typeName.length; i++) {
if ((i+ INDEX)%3 == 0){
continue;
}
set.add(typeName[i].toString());
}
return set;
}
/**
* 获取类方法
* @param loadClass
* @return
*/
protected Method[] getMethod(Class<?> loadClass) {
return loadClass.getDeclaredMethods();
}
/**
* 获取方法参数类型
* @param md
* @return
*/
protected Type[] getType(Method md){
return md.getGenericParameterTypes();
}
/**
* 获取方法参数
* @param md
* @return
*/
protected Parameter[] getParams(Method md){
return md.getParameters();
}
/**
* 检测里面是否有子文件
* @param packages
*/
protected void checkIsParentFile(String[] packages, Class<?> clazz) {
Set<String> set = Arrays.stream(packages).collect(Collectors.toSet());
if (set.contains(null) || set.contains("")) {
throw new RuntimeException("配置包不可含有null或者''");
}
if (packages.length < 2) {
return;
}
for (int i = 0; i < packages.length; i++) {
File f1 = getFile(packages[i],clazz);
for (int j = i + 1; j < packages.length; j++) {
File f2 = getFile(packages[j],clazz);
if (f1.equals(f2.getParentFile()) || f2.equals(f1.getParentFile())) {
throw new RuntimeException(packages[i] + "与" + packages[j] + "是相互包含的关系,选择一个即可");
}
}
}
}
/**
* 根据路径获取对应文件
* @param packagePath
* @return
*/
protected File getFile(String packagePath, Class<?> clazz) {
ClassLoader classLoader = getClassLoader(clazz);
String rePackageName = packagePath.replace(".", "/");
URL resource = classLoader.getResource(rePackageName);
return new File(resource != null ? resource.getFile() : null);
}
/**
* 获取类加载
* @param clazz
* @return
*/
protected ClassLoader getClassLoader(Class<?> clazz) {
return clazz.getClassLoader();
}
/**
* 加载路径方法
* @param filePath
* @param classLoader
* @param start
* @param end
* @return
* @throws ClassNotFoundException
*/
protected Class<?> loadClassByPath(String filePath,ClassLoader classLoader,String start ,String end) throws ClassNotFoundException {
start = Objects.isNull(start)?defParent:start;
end = Objects.isNull(end)?fileType:end;
String classPath = filePath.substring(filePath.indexOf(start), filePath.indexOf("."+end)).replace("\\", ".");
return classLoader.loadClass(classPath);
}
List<File> list ;
/**
* 获取class文件集合
* @param file
* @return
*/
protected List<File> getClassFile(File file){
if (list==null){
list = new ArrayList<>();
}
File[] files = file.listFiles();
if (files==null){
return null;
}
for (File f : files) {
if (f.isFile()){
if (f.getAbsolutePath().endsWith("."+fileType)){
list.add(f);
}
}else {
getClassFile(f);
}
}
return list;
}
/**
* 根据路径获取对应文件
* @param packagePath
* @return
*/
private File getFile(String packagePath,ClassLoader classLoader) {
String rePackageName = packagePath.replace(".", "/");
URL resource = classLoader.getResource(rePackageName);
return new File(resource.getFile());
}
/**
* 获取class文件集合
* @param path
* @return
*/
protected List<File> getClassFile(String path,ClassLoader classLoader){
return getClassFile(getFile(path,classLoader));
}
/**
* 获取class文件集合
* @param path
* @return
*/
List<File> allList = new ArrayList<>();
protected List<File> getClassFileByPack(String path,ClassLoader classLoader){
List<String> paths = StringUtil.strToList(path);
if (paths.isEmpty()){
return null;
}
for (String p : paths) {
List<File> classFile = getClassFile(p, classLoader);
if (classFile!=null){
allList.addAll(classFile);
}
}
return allList;
}
/**
* 获取类所有属性
* @param loadClass
* @return
*/
protected Field[] getFields(Class<?> loadClass) {
Field[] fields = loadClass.getDeclaredFields();
Class<?> superclass = loadClass.getSuperclass();
while (Objects.nonNull(superclass)) {
Field[] superclassFields = superclass.getDeclaredFields();
fields = addFields(fields, superclassFields);
superclass = superclass.getSuperclass();
}
return fields;
}
/**
* 自动创建工厂专用获取类所有属性
* @param loadClass
* @return
*/
protected Field[] getFieldsByAutoCreate(Class<?> loadClass) {
Field[] fields = loadClass.getDeclaredFields();
Class<?> superclass = loadClass.getSuperclass();
while (Objects.nonNull(superclass)) {
if (Objects.nonNull(superclass.getAnnotation(Table.class))) {
Field[] superclassFields = superclass.getDeclaredFields();
fields = addFields(fields, superclassFields);
}
superclass = superclass.getSuperclass();
}
return fields;
}
/**
* 获取类所有属性
* @param loadClass
* @return
*/
protected Method[] getMethods(Class<?> loadClass) {
Method[] methods = loadClass.getDeclaredMethods();
Class<?> superclass = loadClass.getSuperclass();
while (Objects.nonNull(superclass)) {
Method[] method2s = superclass.getDeclaredMethods();
methods = addMethods(methods,method2s);
superclass = superclass.getSuperclass();
}
return methods;
}
/**
* 获取类所有属性
* @param loadClass
* @return
*/
protected Method getMethod(Class<?> loadClass,String methodName) {
Method method = null;
try {
method = loadClass.getMethod(methodName);
if (method!=null){
return method;
}
Class<?> superclass = loadClass.getSuperclass();
while (Objects.nonNull(superclass)) {
method = superclass.getMethod(methodName);
if (method!=null){
break;
}
superclass = superclass.getSuperclass();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return method;
}
/**
* 计算总属性集合
* @param fs1
* @param fs2
* @return
*/
public static Field[] addFields(Field[] fs1, Field[] fs2) {
if (Objects.isNull(fs1) || fs1.length == 0) {
return fs2;
}
if (Objects.isNull(fs2) || fs2.length == 0) {
return fs1;
}
Field[] fields = new Field[fs1.length + fs2.length];
int index = 0;
for (int i = 0; i < fields.length; i++) {
if (i < fs1.length) {
fields[i] = fs1[i];
} else {
fields[i] = fs2[index++];
}
}
return fields;
}
/**
* 计算总属性集合
* @param fs1
* @param fs2
* @return
*/
public static Field[] addField(Field[] fs1, Field fs2) {
if (Objects.isNull(fs2) ) {
return fs1;
}
Field[] fields = new Field[fs1.length + 1];
for (int i = 0; i < fields.length; i++) {
if (i < fs1.length) {
fields[i] = fs1[i];
} else {
fields[i] = fs2;
}
}
return fields;
}
/**
* 计算总方法集合
* @param fs1
* @param fs2
* @return
*/
private Method[] addMethods(Method[] fs1, Method[] fs2) {
if (Objects.isNull(fs1) || fs1.length == 0) {
return fs2;
}
if (Objects.isNull(fs2) || fs2.length == 0) {
return fs1;
}
Method[] fields = new Method[fs1.length + fs2.length];
int index = 0;
for (int i = 0; i < fields.length; i++) {
if (i < fs1.length) {
fields[i] = fs1[i];
} else {
fields[i] = fs2[index++];
}
}
return fields;
}
}
applicationRunner文件下的文件
import com.excu.entity.Column;
import com.excu.factory.demo.AutoCreateTableFactory;
import com.excu.factory.enums.TableStrategy;
import com.excu.service.ColumnsService;
import com.excu.utils.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author: Joyce
* @autograph: Logic is justice
* @date: 2022/05/14-- 1:11
* @describe: 启动时运行自动创建表
*/
@Component
public class BeforeRunner implements ApplicationRunner {
@Value("${auto.entity.package}")
private String ps;
@Value("${auto.source.dbName}")
private String dbName;
@Value("${auto.source.delPath}")
private String path;
@Value("${auto.source.switchFlag}")
private String switchFlag;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private ColumnsService columnsService;
@Override
public void run(ApplicationArguments args) {
//自动生成sql表
autoCreateSqlTable();
//自动注入
// autoInJect();
}
private void autoCreateSqlTable() {
logger.info("开始生成sql文件");
logger.info("扫描数据库:{},驼峰是否开启:{},扫描路径:{},存文件路径 {}",dbName,switchFlag,ps,path);
try {
AutoCreateTableFactory factory = AutoCreateTableFactory.getInstance(Boolean.parseBoolean(switchFlag));
factory.initData(ps);
Map<String, Set<String>> tableSet = factory.getTableSet();
Map<String, List<Column>> map = columnsService.getTableInfoBySet(tableSet.get(TableStrategy.ADD.getCode().toString()), dbName);
Set<String> forceSet = tableSet.get(TableStrategy.FORCE.getCode().toString());
for (String tableName : forceSet) {
List<Column> columns = columnsService.getColumns(tableName, dbName);
if (Objects.isNull(columns)){
continue;
}
Column table = null;
if (columns.isEmpty()){
table = columnsService.getTable(tableName, dbName);
}else {
table = columns.get(0);
}
List<Map<String, Object>> mapTableData = columnsService.getMapTableData(tableName, dbName, 0, 0);
factory.exportSqlFile(columns,mapTableData,table,path);
}
List<String> sqls = factory.getSqls(map);
columnsService.execute(sqls);
//记录新增sql文件
Properties prop = System.getProperties();
String os = prop.getProperty("os.name");
if((os.startsWith("win") || os.startsWith("Win")) && sqls.size()>0){
path+="append.sql";
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String sqlStr="\n-- 时间:"+simpleDateFormat.format(date)+" 数据库名:"+dbName+"--\n";
sqlStr+=sqls.stream().collect(Collectors.joining("\n"));
FileUtils.writeFile(path,sqlStr, true);
}
} catch (Exception e) {
e.printStackTrace();
}
logger.info("生成sql文件完成");
}
}
用法:@Ids @Column 二选一 自己点到注解里面看,以后非空和默认值,小数,主键,自动递增
import com.excu.factory.entity.annotation.auto.Ids;
import com.excu.factory.entity.annotation.auto.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "test", content = "测试", strategy = TableStrategy.ADD)
public class Test {
@Ids()
private Long id;
@Column(name = "name", comment = "名称", length = 255)
private String name;
}
1514

被折叠的 条评论
为什么被折叠?



