使用反射按照类结构生成MySQL表

因为一个表对应一个java类,如果java类多了,一个一个创建表太消耗时间了,同时也想造下轮子。加深下对反射和注解的使用

反射和注解把java一切皆对象的思想完全的体现了出来,同时也给java提供了强大的动态性。

主要进行工作的类,可以在里面加上jdbc,就可以实现自动创建表了。

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class AutoCreatTable {
    private String pre  = "CREATE TABLE ";
    private String bodyPre = "(";
    private String bodySub = ")";
    private String NN     = "NOT NULL";
    private String N      = "NULL";
    private String idAuto      = "AUTO_INCREMENT";
    private String PRIMARY_KEY = "PRIMARY KEY";
    private String ENGINE = "ENGINE=InnoDB";

    private String[] havaLength = {"varchar","char","bit"};
    enum rowType {
       Int("int"),Char("char"),Strings("varchar") ;
        String type;
        rowType(String type) {
            this.type = type;
        }
    }
  public   void creatTable(Class<?> table){
      String[] colum;
      ArrayList<String> pkey = new ArrayList<>();
      int i = 0;
       //获取注解
      Table  tableAnnotation = table.getAnnotation(Table.class);
      if (tableAnnotation == null){
          System.out.println("没使用Table注解");
          return;
      }
      String creatSQL;
      creatSQL = pre + tableAnnotation.name();
      System.out.println(creatSQL);
      Field field[] = table.getDeclaredFields();
      colum = new String[field.length];
        for (Field f:field) {

            f.setAccessible(true);
            Annotation[] annotations = f.getDeclaredAnnotations();
            String name = null;
            String type = null;
            String size = null;
            boolean isiD =false;
            boolean isN  = true;
            if (annotations.length == 0){
                return;
            }
            for (Annotation a:annotations) {
                if (a instanceof Column){

                   if (((Column) a).name().equals("")){
                          typeBean tb = getField(f);
                          name = tb.name;
                   }else {
                       name = ((Column) a).name();
                   }
                   if (((Column) a).type().equals("")){
                       typeBean tb = getField(f);
                       type = tb.type;
                   }else {
                        type = ((Column) a).type();
                   }
                   if (((Column) a).length().equals("")){

                       size = "255";
                   }else {
                       size = ((Column) a).length();
                   }
                   isN = ((Column) a).okNull();
                }
                if (a instanceof Id){
                        isiD = true;
                        pkey.add(f.getName());
                }
            }
            String row = creatRow(name,type,isN,isiD,size);
            colum[i] = row;
            i = i+1;
            System.out.println(row);
        }
      StringBuilder body = new StringBuilder(String.join(",",colum))  ;
        System.out.println(body);
        String[] ks = new String[pkey.size()];
        pkey.toArray(ks);
       body.append(",").append(setPRIMARY_KEY(ks)) ;
       creatSQL = creatSQL+"(" + body + ")"+";";
       System.out.println(creatSQL);
    }
    String creatRow(String name,String type,boolean isnull,boolean isID,String size){
        StringBuilder row = new StringBuilder();
        row.append(name).append(" ");
        //设置类型
        if (size!=null){
            if (haveLength(type)){
                row.append(setSize(type,size)).append(" ");
            }else {
                row.append(type).append(" ");
            }

        }else {
            row.append(type).append(" ");
        }
        //设置字段是否为空
        if (isnull){
            //值为true
             row.append(N).append(" ");
        }else {
             row.append(NN).append(" ");
        }
        //设置id
        if (isID){
            row.append(idAuto).append(" ");
        }
        return row.toString();
    }
    String setPRIMARY_KEY(String ...field){
        String fields = String.join(",",field);
        return this.PRIMARY_KEY+bodyPre+fields+bodySub;
    }
    String setSize(String type,String size){
        return  type+bodyPre+size+bodySub;
    }
    typeBean getField(Field field){
        typeBean tb = new typeBean();
        tb.name = field.getName();
        tb.setType(field.getType().toString());
        return tb;
    }
    boolean haveLength(String type){
        Set<String> set = new HashSet<>(Arrays.asList(havaLength));
      return   set.contains(type);
    }

    public void catTable(Class<?>...classes){
        for (Class c:classes
             ) {
            creatTable(c);
        }

    }
class typeBean{
        String name;
        String type;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        if (type.lastIndexOf("String")!=-1){
            type ="varchar" ;
        }

        this.type = type;
    }
}

}

注解:Column 用于标记表的列,也就是类的字段
代码实现:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String name() default "";
    String length() default "";
    String type() default "";
    boolean okNull() default false;
}

主键注解,用于标记主键

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {


}

表注解,用于标识表,和包扫描配合在一起,就可以实现自动创建、

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String name();
}

测试一下:定义一个类

@Table(name = "testName")
public class User {
    @Id
    @Column
    int uid;
    @Column
    String name;
    @Column(name = "pass",type = "int",okNull = true)
    String pass;
    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPass() {
        return pass;
    }

    public void setPass(String pass) {
        this.pass = pass;
    }
}

测试代码:

 @Test
    public void testAutoCreatTable(){
        AutoCreatTable creatTable = new AutoCreatTable();
        creatTable.catTable(User.class);
    }

测试结果:生成的sql语句

image

看上去没什么大问题。可以进行很多拓展,比如支持所有的mysql类型,支持外键等,还可以自动生成简单crud等。但这样的轮子已经有了,就不重复造了。

posted @   黑猫魔法师  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示