背景
在使用Wrapper構建條件時,經常因為需要構建的條件過多需要寫半個多小時,還容易粗心寫錯欄位,所以就想搞個可以直接自動構建QueryWrapper的工具類。
思路
我們需要一個方法,能夠根據條件引數物件的屬性值來設定QueryWrapper的條件,同時需要返回一個我們所需要對應範型的QueryWrapper。
使用範型來確定返回的QueryWrapper
實現
再獲取欄位名的時候有可能引數類的欄位名不能直接根資料庫表的欄位名直接對應上,所以我直接複用了@TableField 註解,若是欄位上有該註解就直接使用其對應的value屬性值,若是沒有該註解則就使用欄位名,將欄位名的駝峰命名法轉換成下劃線分割的格式。
/**
* 建立對應的wrapper
* @param param 引數物件
* @param <T> 範型
* @return 建立好的wrapper
*/
public static <T> QueryWrapper<T> createWrapper(Object param) {
QueryWrapper<T> wrapper = new QueryWrapper<>();
Class<?> dataClass = param.getClass();
try {
for (Field field : dataClass.getDeclaredFields()) {
field.setAccessible(true);
//獲取欄位型別和欄位值
Class<?> type = field.getType();
Object value = field.get(param);
if (value == null){
continue;
}
//將欄位名轉為資料庫中的欄位名
String fieldName;
TableField tableFieldAnnotation = field.getAnnotation(TableField.class);
if (tableFieldAnnotation != null) {
fieldName = tableFieldAnnotation.value();
}else{
fieldName = convertToSnakeCase(field.getName());
}
//根據欄位的型別來選擇不同的查詢方式
if (type == String.class) {
wrapper.like(fieldName, value);
}else if (type == Long.class){
wrapper.eq(fieldName, value);
}else if (type == List.class){
wrapper.in(fieldName, (List<?>)value);
}else if (type == Between.class){
Between val= (Between)value;
wrapper.between(fieldName, val.getStart(), val.getEnd());
}else{
wrapper.eq(fieldName, value);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return wrapper;
}
/**
* 將駝峰命名法的欄位名轉為下劃線隔開的形式
* @param input 駝峰命名法的欄位名
* @return 下劃線隔開的資料庫欄位名
*/
private static String convertToSnakeCase(String input) {
StringBuilder output = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (Character.isUpperCase(ch)) {
if (i > 0) {
output.append(StrPool.C_UNDERLINE);
}
output.append(Character.toLowerCase(ch));
} else {
output.append(ch);
}
}
return output.toString();
}
測試
可以看到dto引數物件的屬性值都已經填充到了QueryWrapper中