1. 程式人生 > >註解使用示例(解析註解生成建立SQL表語句)

註解使用示例(解析註解生成建立SQL表語句)

當你覺得你用反射的情況非常少的時候,通常就是因為註解接觸的少。

目的

使用註解來自動生成一個建資料庫表的SQL命令。

註解

我們會建立如下的四個註解,用於進行資料庫表,以及欄位本身表述的註解。

  1. @DBTable 代表資料庫表,註解元素name表示表名;
  2. @Constraints
    代表對資料表每一列的條件補充,有primaryKey是不是主鍵,預設false,allowNull是否允許為空,預設true,unique資料是否唯一,預設false;
  3. @SQLString
    代表表中的String列,註解元素value表示列長度,name表示列名,constraints表示對列的一些約束條件;
  4. @SQLInteger 代表表中的int列,name表示列名,constraints表示對列的一些約束條件;

@DBTable

package test1;

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

/**
 * Created by Joe on 2018/2/22.
 */
@Target(ElementType.TYPE)
@Retention
(RetentionPolicy.RUNTIME) public @interface DBTable { public String name() default ""; }

@Constraints

package test1;

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

/**
 * Created by Joe on 2018/2/22.
 */
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Constraints { //主鍵約束 boolean primaryKey() default false; //非空約束 boolean allowNull() default false; //唯一約束 boolean unique() default false; }

@SQLString

package test1;

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

/**
 * Created by Joe on 2018/2/22.
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
    int value() default 0;

    String name() default "";
    //@Constraints後沒有括號表明使用預設值,可以加括號,在裡面定義初始值,比如@Constraints(unique=true)
    Constraints constraints() default @Constraints;

}

@SQLInteger

package test1;

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

/**
 * Created by Joe on 2018/2/22.
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
    String name() default "";
    Constraints constraints() default @Constraints;
}

定義類,使用自定義註解進行標註

package test1;

/**
 * Created by Joe on 2018/2/22.
 */
@DBTable(name = "MEMBER")
public class Member {
    @SQLString(30) String firstName;
    @SQLString(50) String lastName;
    @SQLInteger int age;
    @SQLString(value = 30, constraints = @Constraints(primaryKey = true)) String handle;
    public String getFirstName() {
        return firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public int getAge() {
        return age;
    }
    public String getHandle() {
        return handle;
    }
    public String toString() {
        return handle;
    }
}

定義註解解析器,用於分析註解資訊

package test1;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Joe on 2018/2/22.
 */
public class TableCreator {
    public static void main(String[] args) throws Exception {
        //傳入我們定義好的Bean類名,帶上包名
        Class<?> cl = Class.forName("test1.Member");
        //檢查我們傳入的類是否帶有@DBTable註解
        DBTable dbTable = cl.getAnnotation(DBTable.class);
        List<String> columnDefs = new ArrayList<String>();
        //得到類中的所有定義的屬性
        for (Field filed : cl.getDeclaredFields()) {
            String columnName = null;
            //得到屬性的註解,對一個目標可以使用多個註解
            Annotation[] anns = filed.getAnnotations();
            if (anns.length < 1) {
                continue;
            }
            //SQLString註解走著
            if (anns[0] instanceof SQLString) {
                SQLString sString = (SQLString) anns[0];
                //name()使用的是預設值,所以這裡取屬性名
                if (sString.name().length() < 1) {
                    columnName = filed.getName().toUpperCase();
                } else {
                    columnName = sString.name();
                }
                //構建SQL語句
                columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints()));
            }
            //SQLInteger註解走著
            if (anns[0] instanceof SQLInteger) {
                SQLInteger sInt = (SQLInteger) anns[0];
                if (sInt.name().length() < 1) {
                    columnName = filed.getName().toUpperCase();
                } else {
                    columnName = sInt.name();
                }
                columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints()));
            }
        }
        StringBuilder creator = new StringBuilder("CREATE TABLE " + dbTable.name() + "( ");
        for (String c : columnDefs) {
            creator.append("\n" + c + ",");
        }
        creator.deleteCharAt(creator.length() - 1);
        creator.append(")");
        System.out.println(creator.toString());
    }

    private static String getConstraints(Constraints con) {
        String constraints = "";
        if (!con.allowNull()) {
            constraints += " NOT NULL";
        }
        if (con.primaryKey()) {
            constraints += " PRIMARY KEY";
        }
        if (con.unique()) {
            constraints += " UNIQUE";
        }
        return constraints;
    }
}

執行結果

CREATE TABLE MEMBER( 
FIRSTNAME VARCHAR(30) NOT NULL,
LASTNAME VARCHAR(50) NOT NULL,
AGE INT NOT NULL,
HANDLE VARCHAR(30) NOT NULL PRIMARY KEY)