开发指南094-in语句的处理
微服务架构下,提倡数据库分布,也就是按照业务把数据库分成多个;同时提倡一个微服务只链接一个数据库。这种情况下跨库关联就成了一个问题。尽管从性能考虑不提倡in语句,但是也没有特别好的方法。
一般情况下是这样处理跨库关联(不一定是sql库,也可能非sql库):前端通过一个微服务接口获取关键字字符串,‘A’,'B','C'...然后作为参数调用另一个服务。这时该服务就不可避免使用in语句了。但是数据库这边对in的参数数量有限制,而且测试表明,拆分成多个or,比直接用in要快。
根据这些,底层提供了CommonsUtil.splitInSql函数:
public static String splitInSql(String[] ids, String fieldName) { StringBuffer sqlStr = new StringBuffer(); if (ids == null || ids.length == 0 || fieldName == null || "".equals(fieldName)) return null; int len = ids.length; int num = 1; if (len > 500) num = (len % 500 == 0) ? len / 500 : (len / 500) + 1; int j = 0; int i = 1; Hashtable hash = new Hashtable(); for (; i <= num; i++) { StringBuffer sb = new StringBuffer(); String str = ""; for (; j < i * 500 && j < len; j++) { if (ids[j] == null || "".equals(ids[j]) || hash.containsKey(ids[j])) continue; sb.append("'") .append(ids[j]) .append("',"); hash.put(ids[j], ""); } str = sb.toString(); str = str.substring(0, str.length() - 1); sqlStr.append("or ").append(fieldName).append(" in (").append(str).append(") "); } hash.clear(); hash = null; if (sqlStr.length() > 0) { sqlStr.delete(0, 2); return "(" + sqlStr.toString() + ")"; } else return "(" + fieldName + " in (''))"; }