想將實體類字段轉為數據庫字段,找了半天只找到一個這樣的例子:
/** * 對象屬性轉換為數據庫字段。例如:userName => user_name * * @param property * 對象屬性 */ public static String propertyToField(String property) { if (StringUtils.isEmpty(property)) { return ""; } if (property.length() == 1) { return property.toLowerCase(); } char[] chars = property.toCharArray(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (i == 0) { sb.append(StringUtils.lowerCase(CharUtils.toString(c))); } else { if (CharUtils.isAsciiAlphaUpper(c)) { sb.append("_" + StringUtils.lowerCase(CharUtils.toString(c))); } else { sb.append(c); } } } return sb.toString(); }
一般情況下,這個方法都是滿足需求的,可以測試一下:
System.out.println(propertyToField("UserName")); // user_name System.out.println(propertyToField("sUserName")); // s_user_name System.out.println(propertyToField("isUserName")); // is_user_name System.out.println(propertyToField("age")); // age
但是如果實體類中,出現連續的大寫字母(這種情況不符合java規范),就會很怪異:
System.out.println(propertyToField("settID")); // sett_i_d System.out.println(propertyToField("APartyName")); // a_party_name
看了下JPA自動把實體類字段轉為數據庫字段的效果,發現它直接跳過了連續大寫字母,只在形如"..aAa..."這樣的情況中做轉換
於是寫了一個將字符串中,連續兩個及兩個以上的字符替換成小寫的方法。代碼如下:
/** * 將property字符串中,連續兩個及兩個以上的字符替換成小寫 */ private static String lowerConStr(String property) { // 記錄連續大寫字母。元素組成:連續大寫字母首個字母下標 + "_" + 連續大寫字母個數 List<String> uppList = new ArrayList<>(); String info = ""; char[] chars = property.toCharArray(); char c = chars[0]; int count = 1; // 記錄連續大寫字母個數 for (int i = 1; i < chars.length; i++) { // 上個字符是否大寫 boolean isSep = CharUtils.isAsciiAlphaUpper(c); char s = chars[i]; // 當前字符是否大寫 boolean isCurrUp = CharUtils.isAsciiAlphaUpper(s); // 連續大寫,記錄下來 if (isSep && isCurrUp) { if (StringUtils.isEmpty(info)) { info = (i - 1) + "_"; } count++; if (i == chars.length - 1) { String wordInfo = info + count; uppList.add(wordInfo); } } else { if (count > 1) { String wordInfo = info + count; uppList.add(wordInfo); count = 1; info = ""; } } c = s; } String lower = lower(property, uppList); // System.out.println(property + " => " + lower); return lower; } /** * 將property中連續大寫字母,根據uppList記錄,轉為小寫 */ private static String lower(String property, List<String> uppList) { StringBuilder sb = new StringBuilder(property); for (String str : uppList) { String[] arr = str.split("_"); int index = Integer.valueOf(arr[0]); int count = Integer.valueOf(arr[1]); String r = property.substring(index, index + count); sb.replace(index, index + count, r.toLowerCase()); } return sb.toString(); }
然后在最上面的propertyToField方法中增加一行:
if (property.length() == 1) { return property.toLowerCase(); } // 將property字符串中,連續兩個及兩個以上的字符替換成小寫 property = lowerConStr(property); char[] chars = property.toCharArray(); StringBuffer sb = new StringBuffer(); ...
再來看測試結果,都是正確的:
System.out.println(propertyToField("UserName")); // user_name System.out.println(propertyToField("sUserName")); // s_user_name System.out.println(propertyToField("isUserName")); // is_user_name System.out.println(propertyToField("age")); // age System.out.println(propertyToField("settID")); // settid System.out.println(propertyToField("APartyName")); // aparty_name
最后再送一個在網上找到的,數據庫字段轉換為實體類字段的方法:
/** * 字段轉換成對象屬性 例如:user_name to userName * * @param field * @return */ public static String fieldToProperty(String field) { if (null == field) { return ""; } char[] chars = field.toCharArray(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c == '_') { int j = i + 1; if (j < chars.length) { sb.append(StringUtils.upperCase(CharUtils.toString(chars[j]))); i++; } } else { sb.append(c); } } return sb.toString(); }
