Java註解學習,反射機制獲取由註解標記的信息並構建sql查詢語句

java註解學習筆記

一、jdk中的註解

jdk中都屬於編譯時註解,在編譯前就會提示錯誤,總共有兩種註解:

  1. @Deprecated 註解
    表示方法已過時
  2. @Suppress Warning註解:忽略由Deprecated註解造成的警告

二、java第三方註解

這裏只列舉了Spring和Mybatis中常見的幾個

  • Spring中的註解
    • @Autowired註解
    • @Service註解
    • @Repository註解
  • Mybatis中的註解
    • @InsertProvider
    • @UpdateProvider
    • @Options

三、註解的分類

  • 源碼註解
  • 編譯時註解
  • 運行時註解
  • 元註解:給註解進行註解
    • @Target(ElementType.XXXX)
      作用:用於描述註解的使用範圍(即:被描述的註解可以用在什麼地方)
        取值(ElementType)有:
          1. CONSTRUCTOR:用於描述構造器
          2. FIELD:用於描述域即類成員變量
          3. LOCAL_VARIABLE:用於描述局部變量
          4. METHOD:用於描述方法
          5. PACKAGE:用於描述包
          6. PARAMETER:用於描述參數
          7. TYPE:用於描述類、接口(包括註解類型) 或enum聲明
      最常用的TYPE(描述類)、METHOD(描述方法)、FIELD(描述成員變量)
    • @Retention(RetentionPolicy.RUNTIME)
    • Inherited :是一個標記註解。
      @Inherited闡述了某個被標註的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。
      • Documented :是一個標記註解,表示可用於javadoc工具的文檔化

四、自定義註解

成員類型是受限的,合法的類型包括原始類型及String, Class, Annotation, Enumeration
同一個類文件只能被同一個類加載器對象加載一次

最簡化的註解定義:

@Target({ ElementType.TYPE})   //定義在類上的註解
@Retention(RetentionPolicy.RUNTIME)     //運行時註解
@Inherited   //可被繼承
@Documented   //可用於文檔化
public @interface UdfAnnotation {
    String value();
}

五、代碼實操

通過反射機制獲取由註解標記的信息並構建sql查詢語句


/**
 * Person實體類,通過Table和Column註解標記表名和列明
 */
@Table("person")
public class Person {

    @Column("id")
    private String id;

    @Column("name")
    private String name;

    @Column("age")
    private Integer age;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }


    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


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

/**
 * Column自定義註解
 */
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    public String value();
}


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

/**
 * Table自定義註解,用於標記表名
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    public String value();
}


import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 測試類,用於從註解中獲取信息並構建sql語句
 */
public class Test {

    public static void main(String[] args){

        Person p1 = new Person();
        p1.setId("1");

        Person p2 = new Person();
        p2.setName("kevin,lily");

        Person p3 = new Person();
        p3.setAge(10);

        String q1 = query(p1);
        String q2 = query(p2);
        String q3 = query(p3);

        System.out.println(q1);
        System.out.println(q2);
        System.out.println(q3);
    }

    public static String query(Object obj){
        StringBuilder sql = new StringBuilder();

        try {
            Class c = Class.forName("com.example.demo.bases.reflect.project.Person");
            if (c.isAnnotationPresent(Table.class)){
                Table table = (Table)c.getAnnotation(Table.class);
                String tableName = table.value();
                //System.out.println(tableName);
                sql.append("select * from ").append(tableName).append(" where 1=1");

                Field[] fields = c.getDeclaredFields();
                for(Field field : fields){
                    String columnName = ((Column)field.getAnnotation(Column.class)).value();
                    //System.out.println("列名:"+columnName);

                    // 得到方法名,並利用invoke通過方法名獲取到參數值
                    String methodName = "get"+columnName.substring(0,1).toUpperCase()+columnName.substring(1);
                    //System.out.println("方法名:"+methodName);
                    Method method = c.getDeclaredMethod(methodName);
                    Object mValue = method.invoke(obj);
                    //System.out.println("方法值:"+mValue);

                    if (mValue instanceof Integer){
                        sql.append(" and ").append(columnName).append("=").append(mValue);
                    }
                    if (mValue instanceof String){
                        if (((String) mValue).contains(",")){
                            String[] values = ((String)mValue).split(",");
                            for (String value : values){
                                sql.append(" and ").append(columnName).append("=").append("'").append(value).append("'");
                            }
                        }else{
                            sql.append(" and ").append(columnName).append("=").append("'").append(mValue).append("'");
                        }
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return sql.toString();
    }
}

運行結果:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章