使用注解開發的好處就是減少配置文件的使用。在實際過程中,隨着項目越來越復雜,功能越來越多,會產生非常多的配置文件。但是,當配置文件過多,實際維護過程中產生的問題就不容易定位,這樣就會徒勞的增加工作量。而使用注解開發,可以減少配置文件的使用,方便代碼的維護,同時,在開發速度上也有大幅提升,因此,學會使用注解開發,是有必要掌握的一項技能。
下面為各位展示下使用注解開發自動生成SQL語句的過程。
首先先定義一個實體類,用於和數據庫字段進行映射,為了方便,數據庫字段名稱和實體類變量名稱保持一致。
package com.huawei.andrid.net.annotation; @Table("person") public class Person { @Column("name") private String name; @Column("sex") private String sex; @Column("id") private int id; @Column("age") private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
下面我們要為這個實體類定義注解,包含@Table和@Column兩個注解。
package com.huawei.andrid.net.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Documented @Retention(RUNTIME) @Target(TYPE) public @interface Table { public String value(); }
元注解:
@Documented 生成javadoc時,支持注解
@Retention(RUNTIME) 注解的生命周期
@Target(TYPE) 注解的在類上
package com.huawei.andrid.net.annotation; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Documented @Retention(RUNTIME) @Target(FIELD) public @interface Column { public String value(); }
最后,我們需要解析注解,使用java的反射機制。
private static String query(Object p) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { StringBuilder str = new StringBuilder(); //通過反射獲取Class對象,以便獲取注解的值 Class<? extends Object> obj = p.getClass(); //判斷該對象的類上有沒有注解@Table boolean isExistsTable = obj.isAnnotationPresent(Table.class); if (!isExistsTable) { return null; } //獲取Table注解,並獲取注解的值,即表名 Table table = (Table) obj.getAnnotation(Table.class); String tableName = table.value(); //拼裝sql str.append("select * from ").append(tableName).append(" where 1=1 "); //獲取所有的成員變量,並遍歷出來成員變量上的注解值 Field[] fields = obj.getDeclaredFields(); for (Field field : fields) { Boolean isExistColumn = field.isAnnotationPresent(Column.class); if (!isExistColumn) { continue; } //獲取成員變量上的注解值 Column column = field.getAnnotation(Column.class); String columnName = column.value(); //獲取成員變量的get方法名 String methodName = "get" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1); //獲取成員變量的get方法 Method method = obj.getMethod(methodName); //執行成員變量的get方法,參數為該對象 Object value = method.invoke(p); //過濾掉成員變量中的null值,以及0 if (null == value || (value instanceof Integer && (Integer) value == 0)) { continue; } str.append(" and ").append(columnName).append("=").append(value); } return str.toString(); }
測試:
public static void main(String[] args) { Person p = new Person(); p.setName("wanglu"); p.setAge(25); String querySQL = null; try { querySQL = query(p); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } System.out.println(querySQL); }