我們在項目開發中有很多地方使用到了註解,關於註解的定義與創建小伙伴可以參考我的文章《java註解》。有任何問題的小伙伴們可以在評論區指出哦,歡迎各位大佬指出問題。 今天我要說的是使用註解與反射結合使用,來使我們代碼根據優雅,更加高大上(咳,裝逼神器啊)。 註解使用@interface 來定義,辣麽我 ...
我們在項目開發中有很多地方使用到了註解,關於註解的定義與創建小伙伴可以參考我的文章《java註解》。有任何問題的小伙伴們可以在評論區指出哦,歡迎各位大佬指出問題。
今天我要說的是使用註解與反射結合使用,來使我們代碼根據優雅,更加高大上(咳,裝逼神器啊)。
註解使用@interface 來定義,辣麽我們自定義的註解,該使用獲取到並且指明該註解的作用呢?java提供了反射機制,通過類的類類型我們可以根據自己需要老操作該類。有管反射的知識,可以參考我的上兩章博客。好了,廢話不多說,我們上代碼:
需求:創建一個與資料庫表對應的實體類,通過使用註解的方式,來生成該實體類的查詢sql語句。
1.創建Table類註解,用於標明該類對應資料庫的表名稱
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(); }
2.創建Column欄位註解,用於標明該類中屬性與資料庫表欄位的映射
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(); }
3.創建實體類,並使用註解Table、Column
/** * 資料庫 user表,對應表欄位為 userid/username/age/addredd */ @Table("user") public class User { @Column("userid") private String userid; @Column("username") private String username; @Column("age") private int age; @Column("sl") private double sl; @Column("address") private String address; // 添加一個不是資料庫的欄位: 用於測試 private String noField; public double getSl() { return sl; } public void setSl(double sl) { this.sl = sl; } public String getNoField() { return noField; } public void setNoField(String noField) { this.noField = noField; } public String getUserid() { return userid; } public void setUserid(String userid) { this.userid = userid; } 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 getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
4.創建工具類,根據傳入該對象,來生成對應的查詢sql
import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Objects; /** * 註解 */ public class AnnotationUtil { /** * 根據傳入的對象 來生成query sql * * @param object * @return */ public static String getSqlByAnnotation(Object object) throws Exception { // 使用StringBuilder 線程安全 StringBuilder sb = new StringBuilder(); // 檢查參數是否為空 Objects.requireNonNull(object, "該對象不能為空!"); // 1.通過反射獲取該對象的類類型 Class c = object.getClass(); // 2.獲取該對象的 類註解: 標明表名 boolean table_flag = c.isAnnotationPresent(Table.class); if (!table_flag) { throw new NullPointerException(); } Table table = (Table) c.getDeclaredAnnotation(Table.class); sb.append("SELECT * FROM ").append(table.value()).append(" WHERE 1 = 1"); // 3.獲取該對象的 欄位註解:顯示查詢欄位 Field[] fields = c.getDeclaredFields(); boolean field_flag; Column column; String field_name; Method menthod; Object val; for (Field field : fields) { // 首先得拿到欄位名稱:通過欄位上的註解標明該指定是資料庫表對應的欄位 field_flag = field.isAnnotationPresent(Column.class); if (!field_flag) { continue; } column = field.getDeclaredAnnotation(Column.class); // 其次得拿到欄位值 : 通過反射調用類的getXxxx方法 field_name = field.getName(); menthod = c.getDeclaredMethod("get" + Character.toUpperCase(field_name.charAt(0)) + field_name.substring(1)); val = menthod.invoke(object); // 判斷該欄位是否為空,不為空,才進行append // 這裡要註意:有些屬性不賦值時候,java會自動生成預設值,如Double預設為0.0 // 還有其他類型,小伙伴們可以自行測試 if (!Objects.isNull(val)) { if((val instanceof Double) && (double) val == 0.0){ continue; } sb.append(" AND ").append(column.value()).append(" = "); sb.append(val); } } return sb.toString(); } public static void main(String[] args) { User user = new User(); user.setUserid("0001"); user.setAge(23); // 用於測試沒有帶Column註解的欄位 user.setNoField("field"); try { System.out.println(AnnotationUtil.getSqlByAnnotation(user)); } catch (Exception e) { e.printStackTrace(); } } }