前言:
现在各位老铁们对“java split 方法详解”大概比较珍视,兄弟们都需要知道一些“java split 方法详解”的相关文章。那么小编也在网摘上搜集了一些有关“java split 方法详解””的相关知识,希望朋友们能喜欢,大家一起来了解一下吧!前两天在排查个bug,问题的根节倒是不复杂,但整个过程也是小有收获。
埋雷
数据库实体中有这么个字段:
@Convert(converter = MapConverter.class)private Map<String, String> links;
MapConverter的实现
public class MapConverter implements AttributeConverter<Map<String, String>, String> { @Override public String convertToDatabaseColumn(Map<String, String> strMap) { return strMap == null ? null : strMap.toString(); } @Override public Map<String, String> convertToEntityAttribute(String s) { // 空值处理 try { Map<String, String> map = new IdentityHashMap<>(); // DB的列存的是字符串,形如 {key1=val1, key2=val2}, 所以这里去掉首尾的大括号,然后切分 String string = s.substring(1, s.length() - 1); String[] list = string.split(","); for (String str : list) { String[] con = str.trim().split("="); map.put(con[0], con[1]); } return map; } catch (Exception e) { ... } ... }}
在这个ORM模型中,MapConverter定义了将对象中的Map结构如何存储到数据库的列中,以及如何从列解析到对象中。
踩雷
在生产环境,发现存入:
strMap.put("toutiao", ";)strMap.put("xiaomi", ";)
读取出来的toutiao链接仅为";
而且在存入DB接口,返回结果是正常的;查询结果就是不正常,而且更新其他字段后,发现DB中存的也仅仅是"{toutiao=, ...}".
在排除了缓存等原因之后,将目光聚焦到MapConverter上,但是:convertToDatabaseColumn方法,不可能存在截断处理,那为什么DB中存的是不完整的链接了?
难不成convertToEntityAttribute这个负责读取DB内容进行解析映射的方法能兴风作浪?
屏气读到:
String[] con = str.trim().split("=");
会发现,split没有填入任何参数,这意味着切分所用的pattern将被尽可能多的执行,所以它取con[1]只能取到";,这能解释了读取的问题
但是它如何影响DB中的存储结果了?
因为用的是ORM嘛
当你更新时,先查询这个对象,这个时候,会用到"convertToEntityAttribute", 它已经背弃你的初衷,返回了一个错误的结果;然后更新实体对象,持久化到DB中,这时DB的结果自然也是错误的。
清雷
那如何解决了?
造轮子这种事情还是要谨慎的,如果可以交给Jackson去转换,可以大大降低这种各种边际情况的发生吧
那非要自己切分了?split的limit的请了解一下:
split其实就是用正则表达式去匹配提取,它的另一个参数limit常常会被忽视,但确实非常重要的参数。
public String[] split(String regex, int limit)regex -- 这是在限定的正则表达式。limit -- 这个控制模式施加的数的次数,因此,会影响所得到的数组的长度
总的来说:
如果 n < 0,那么模式将被应用尽可能多的次数,而且数组可以是任何长度。如果 n = 0,那么模式将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃。如果 n > 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的最后一项将包含所有超出最后匹配的定界符的输入。
应用在本处, 上述可改成如下(记得在放进map的时候,加上NPE判断等)
String[] con = str.trim().split("=", 2);
标签: #java split 方法详解