使用Java註解將實體類轉化為sql字串
阿新 • • 發佈:2018-12-31
首先是定義一個實體類,如下
/* * 定義使用者,通過註解對映到資料庫 */ @Table("user") public class User { @Column("id") private int id; @Column("username") private String username; @Column("nickname") private String nickName; @Column("age") private int age; @Column("email") private String email; @Column("mobile") private String mobile; public User(){ // } 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 String getNickname() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } }
上面有類註解和方法註解,分別new一個Annotation,
其中註解裡面只有一個值,因此直接用value()宣告即可
Table.java
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /*ElementType引數有 * CONSTRUCTOR:構造器的宣告 * FIELD:域,屬性的宣告 * LICAL_VARIABLE:區域性變數的宣告 * PACKAGE:包宣告 * PARAMETER:引數宣告 * TYPE:類,介面(包括註解型別)或enum宣告 * */ @Target({ElementType.TYPE}) /* * 需要儲存的級別 * SOURCE:註解將被編譯器丟掉 * CLASS:註解在class檔案中可以使用,會被VM丟掉 * RUNTIME:VM將在執行時也保留註解,因此可以通過反射機制讀取註釋的資訊 */ @Retention(RetentionPolicy.RUNTIME) public @interface Table { String value(); }
Column.java
//定義一個描述使用者表屬性欄位的註解 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(); }
然後是轉換函式
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//將傳入的使用者資訊轉換為sql語句
public class ToSql {
public static String query(Object u){
StringBuilder sqlstr=new StringBuilder();
//獲取到class
Class c=u.getClass();
// 檢視是否包含Table型別的註解
if(!c.isAnnotationPresent(Table.class)){
return null;
}
//如果包含,獲取到Table類,並通過此獲取到Table類註解
Table table=(Table)c.getAnnotation(Table.class);
String tableName=table.value();
//先將sql語句的前半部分寫入
sqlstr.append("SELECT * FROM ").append(tableName).append(" WHERE 1=1");
//獲取所有自己宣告的屬性
Field[] fields=c.getDeclaredFields();
//遍歷屬性
for (Field field : fields) {
//通過註解中的值來獲取屬性名(註解中的值應該與屬性名相等)
String columnValue=field.getAnnotation(Column.class).value();
//獲取屬性的get方法的方法名,方法名的寫法一般為get+屬性名(屬性名的第一個字母大寫)
String getMethodName="get"+columnValue.substring(0, 1).toUpperCase()+columnValue.substring(1);
//使用反射通過方法名獲取方法,並呼叫invoke方法執行該方法,得到返回值
Object fieldValue=null;
try {
Method getMethod=c.getMethod(getMethodName);
fieldValue=getMethod.invoke(u);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
System.out.println("MethodName="+getMethodName);
e.printStackTrace();
}
//因為是遍歷所有的方法,所以有些方法是沒有賦值的,也就是不需要查詢,將其剔除
if(fieldValue==null||((fieldValue instanceof Integer) &&((Integer)fieldValue==0))){
continue;
}
sqlstr.append(" AND ").append(columnValue);
//判斷字串,多箇中滿足任何一個用IN,並使用''
if(fieldValue instanceof String){
//感覺介面太神奇了
if(((String)fieldValue).contains(",")){
String[] values=((String)fieldValue).split(",");
sqlstr.append(" IN(");
for (String string : values) {
sqlstr.append("'").append(string).append("'").append(",");
}
//刪除最後一個","
sqlstr.deleteCharAt(sqlstr.length()-1);
sqlstr.append(")");
}else{
//字串表示法
sqlstr.append("=").append("'").append(fieldValue).append("'");
}
}else if (fieldValue instanceof Integer) {
sqlstr.append("=").append(fieldValue);
}
}
return sqlstr.toString();
}
}
Test.java測試類
public class Test {
public static void main(String[] args) {
User user=new User();
user.setEmail("[email protected],[email protected]");
System.out.println(ToSql.query(user));
}
}