java注解,通過反射解析注解,模仿hibernate,獲取sql語句。


常用注解:

自定義注解,標准格式:

1,target:注解作用域

2,Retention:聲明周期

運行子類繼承,但是子類繼承只能作用到類注解,字段注解,是繼承不了的。

使用注解:通過下面這種方式,為注解的成員賦值,使用的時候會通過成員名,找到這些值,去使用這些值。

如果注解只有一共成員,該成員必須命名為value,這樣使用注解的時候方便:如:@注解(“值1”),相當於@注解(value=“值1”);

 

解析注解:

解析注解主要用到反射的方式,在下面的例子中可以看到。 

主要代碼如下:

        //1,獲取到class
        Class c=f.getClass();
        //2,獲取到table的名字
        boolean exists=c.isAnnotationPresent(Table.class);//判斷該類Filete是否是包含注解Table
        if(!exists)
        {
            return null;
        }
        Table t=(Table) c.getAnnotation(Table.class);//取出Filete這個類的Table注解
        String tableName=t.value();//獲取該注解的值

 

 

使用注解模仿hibernate獲取sql的方法。

1,定義兩個注解,Table和column

package com.Annotation;

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

@Target({ElementType.TYPE})    //作用域為在類上
@Retention(RetentionPolicy.RUNTIME)    //生命周期為運行時

public @interface Table {
    String value();
}

package com.Annotation;

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

@Target({ElementType.FIELD})    //作用域為在字段上
@Retention(RetentionPolicy.RUNTIME)    //生命周期為運行時

public @interface Column {
    String value();
}

2,定義一個數據庫模型類:並分別在類名和字段名上加上注解,分別跟表名和字段名關聯

package com.Annotation;

@Table("user") public class Filter {
    @Column("id") private int id;
    @Column("user_Name") private String userName;
    @Column("age")
    private int age;
    @Column("city")
    private String city;
    @Column("email")
    private String email;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getEmail() {
        return email;
    }
    public void setemail(String email) {
        this.email = email;
    }
}

3,通過set字段值,來定義查詢條件,定義一共querey方法,同注解,反射獲取sql。

package com.Annotation;

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

public class Test {

    public static void main(String[] args) {

        Filter f1=new Filter();
        f1.setAge(10);//查詢id為10的用戶
        
        Filter f2=new Filter();
        f2.setCity("大連");//查詢城市為大連的用戶
        
        Filter f3=new Filter();
        f3.setCity("liu@sina.com,zh@sina.com,8888@163.com");
        //查詢郵箱為上面的用戶
        
        String sql1=query(f1);
        String sql2=query(f2);
        String sql3=query(f3);
        System.out.println(sql1);
        System.out.println(sql2);
        System.out.println(sql3);
    }
    private static String query(Filter f)
    {
        StringBuffer sb=new StringBuffer();
        //1,獲取到class
        Class c=f.getClass();
        //2,獲取到table的名字
        boolean exists=c.isAnnotationPresent(Table.class);//判斷該類Filete是否是包含注解Table
        if(!exists)
        {
            return null;
        }
        Table t=(Table) c.getAnnotation(Table.class);//取出Filete這個類的Table注解
        String tableName=t.value();//獲取該注解的值
        sb.append(" select * from ").append(tableName).append("where 1=1");
        //3,遍歷所有字段
        Field[] fArray=c.getDeclaredFields();
        for(Field field:fArray)
        {
            //4,處理每個字段對應的sql
            //4,1,拿到字段名
            boolean fExis=field.isAnnotationPresent(Column.class);
            if(!exists)
            {
                continue;
            }
            Column column=field.getAnnotation(Column.class);//獲取該字段上的column注解
            String columnName=column.value();
            
            //4,2,拿到字段的值
            String filedName=field.getName();
            String getMethoudName="get"+filedName.substring(0,1).toUpperCase()+
                    filedName.substring(1);
            Object fieldValue = null;//為了讓各種類型的返回值都能接收,定義Object類型
            try {
                Method getMethod=c.getMethod(getMethoudName);
                fieldValue=getMethod.invoke(f);//調用f的對應字段的get方法
            } catch (Exception e) {
                e.printStackTrace();
            } 
            
            //4,3,拼裝sql
            if(fieldValue==null||
                    (fieldValue instanceof Integer && (Integer)fieldValue==0))
            {
                continue;
            }
            sb.append(" and ").append(filedName);
            if(fieldValue instanceof String)    //如果字符串是Int類型,加上單引號
            {
                if(((String) fieldValue).contains(",")) //包含,,表示是子查詢
                {
                    String []values=((String) fieldValue).split(",");
                    sb.append("in(");
                    
                    for(String v:values)
                    {
                        sb.append("'").append(v).append("'").append(",");
                    }
                    sb.deleteCharAt(sb.length()-1);//去掉最后一個逗號
                    sb.append(")");
                }
                else    //否則是普通查詢
                {
                    sb.append("=").append("'").append(fieldValue).append("'");
                }
            }
            else if(fieldValue instanceof Integer)
            {
                sb.append("=").append(fieldValue);
            }
        }
        return sb.toString();
    }
}

運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM