在使用Wrapper構建條件時,經常因為需要構建的條件過多需要寫半個多小時,還容易粗心寫錯欄位,所以就想搞個可以直接自動構建QueryWrapper的工具類。 ...
背景
在使用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中