SqlDdlDaoStreamAsyncImpl 是 SqlDdlDao 的流式异步查询实现。
支持对一个无界流同时执行一批 sql 语句, 从而大幅降低数据库负载。
// 用一个流构造 dao, stream 中可以是 map 也可使是 java bean
SqlDdlDaoStreamAsyncImpl asyncDao = new SqlDdlDaoStreamAsyncImpl(stream);
// 向流中注册多条 sql 语句, 这些 sql 语句的执行对象相同, 逻辑互不相关
String sql1 = "select count(*) as c from stream group by count";
Callback<List<Map<String, Object>>> callback1 = asyncDao.sqlFindListMap(sql1);
String sql2 = "select type, count(*) as c from stream group by count";
Callback<List<Map<String, Object>>> callback2 = asyncDao.sqlFindListMap(sql2);
String sql3 = "select name, count(*) as c from stream group by name";
Callback<List<Map<String, Object>>> callback3 = asyncDao.sqlFindListMap(sql3);
// 利用 count 消费流, 每一条数据被消费时, 所有 callback 中的数据都会被立刻更新。
sqlDdlDaoStreamAsync.count();
// 从 Callback 中获取返回值, 即使流没有被消费完, callback1 也可以放到其他线程中去 get()。
List<Map<String, Object>> listMap1 = callback1.get();
List<Map<String, Object>> listMap2 = callback2.get();
List<Map<String, Object>> listMap3 = callback3.get();
注意: SqlDdlDaoStreamAsyncImpl 目前的版本不支持子查询和联合查询, 后期考虑优先支持支持子查询。
SqlDdlDaoStreamAsyncImpl 支持传入 parallel 流, 此时 SqlDdlDaoStreamAsyncImpl 将会因为多线程执行而提高速度。
但是, parallel 流会增加 SqlDdlDaoStreamAsyncImpl 的内存占用, 并导致 first, last,list 等顺序敏感的 UDAF 函数返回值的变化。
DatasSqlDqlEngine 是针对内存中 List 数据执行 sql 语句的工具。
用于处理那些非数据库数据,比如 xls / csv 中的数据。
该系列有3个实现类:
sybn util 中提供了读写 excel 的工具类,并支持将 spring mvc 的数据 view 转换为excel.
主要有以下功能:
// 读取 excel, 支持 xls, xlsx 格式
List<Object[]> readExcel = PoiReadObjUtil.readExcelObject(new File("D:/xxx.xls"));
List<Map<String, Object>> maps = PoiReadObjUtil.arraysToMaps(readExcel);
LogUtil.info("\r\n", ListLogUtil.conver(maps, 32)); // 打印日志时最大列宽为32
// 写入 excel
ExcelBuilder builder = ExcelBuilderFactory.getExcelBuilder("文件名.xls", "excel标题", list);
builder.exportToLocalFile(new File("D:/"));
// 从 String 读取 csv
String csv = "a,b\r\n\"1\",2\r\n11,22\r\n111,222\r\n";
List<String[]> converterByStr = converterByStr(csv);
List<Map<String, Object>> maps = PoiReadObjUtil.arraysToMaps(converterByStr);
LogUtil.info("\r\n", ListLogUtil.conver(maps, 32)); // 打印日志时最大列宽为32
// 从文件读取 csv (支持 InputStream 或者 文件名 读取)
List<String[]> converterByStr = converter("D:/xxx.csv", Charsets.UTF_8);
List<Map<String, Object>> maps = PoiReadObjUtil.arraysToMaps(converterByStr);
LogUtil.info("\r\n", ListLogUtil.conver(maps, 32)); // 打印日志时最大列宽为32
// 读取 InputStream 到 Stream
String csv = "a,b\r\n\"1\",2\r\n11,22\r\n111,222\r\n";
InputStream is = new ByteArrayInputStream(csv.getBytes());
Stream<String[]> stream = converterStream(is, Charsets.UTF_8);
Stream<Map<String, Object>> stream2 = PoiReadObjUtil.arraysToMaps(stream);
stream.colse(); // 关闭 InputStream
List<Map<String, Object>> converterByStr2 = stream2.collect(Collectors.toList());
LogUtil.info("\r\n", ListLogUtil.conver(converterByStr2, 32)); // 打印日志时最大列宽为32
sybn counter 是一个多线程计数器, 此接口的两个实现 SybnCounterImpl 和 SybnCounterMapImpl 都是线程安全的. sybn counter 主要有以下功能:
import cn.sybn.bean.counter.SybnCounter;
import cn.sybn.bean.counter.SybnCounterImpl;
SybnCounter count = new SybnCounterImpl();
count.setCount("aaa", 1);
count.incCount("aaa", 1);
long aaa = count.getCount("aaa"); // 2
count.setTotal(100);
count.incCurrent(10);
String log = count.toCountString(); // {progress:10/100( 10.00%), currentTime:1ms, remainTime:9ms, aaa:2}
@Test
public void mainTest() {
// 测试并发 300 个线程同时写入
final SybnCounterImpl c = new SybnCounterImpl();
ExecutorService service = Executors.newFixedThreadPool(300);
for (int i = 0; i < 1000; i++) {
service.execute(new SybnCounterUtil.SybnCounterTestThread(c, i));
}
service.shutdown();
try {
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
LogUtil.info(c);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
LogUtil.getLogger().error("", e);
}
SybnCounterImpl c2 = new SybnCounterImpl(false);
c2.setCount("a", 1);
c2.incCount("a", 1);
c2.clearCount("a");
c2.incCount("a", 1);
Assert.assertEquals(1, c2.getCount("a"));
}
maven 和 spring boot 都提供了各自的多环境切换方案,sybn util 工具包中也有自己的解决方案。
此方案用于在多个环境中切换配置文件, 甚至在运行时指定 jar/war 包以外的任意系统目录中的的配置文件。
优点: 在开发和部署时可以使用完全相同的程序包,不用像 maven 那样去手动切换环境,而是像 spring boot 那样通过命令行参数,或者运行时环境变量来决定配置文件。
提示:
ReadConfUtil 属于 cn.sybn.singleutil 包.
因此他是一个独立工具类,在必要时直接将这个类复制到其他项目中可以单独使用,不需要依赖整个 sybn util 包。
## sybnuitl_test.properties
# 不带空格,实际值:"111111"
value1=111111
# 前后带空格,会被忽略,实际值:"222222"
value2 = 222222
# 变量内含变量,会被替换,实际值:"333111111333"
value3=333${value1}333
// 从默认配置文件获取属性值
System.setProperty(SYBN_CONF, "sybnuitl_test.properties");
// or java -jar -DSYBN_CONF=sybnuitl_test.properties
String value = ReadConfUtil.getValue("value1"); // 111111
// 从指定配置文件获取属性值
// value1 = 111111
String value1 = ReadConfUtil.getValue("value1@sybnuitl_test.properties"); // jar中搜索配置文件
// value2 = 222222
String value2 = ReadConfUtil.getValue("value2@./sybnuitl_test.properties"); // 相对路径配置文件
// value3 = 333111111333
String value3 = ReadConfUtil.getValue("value3@/usr/local/sybn/sybnuitl_test.properties"); // 绝对路径
// 从变量中指定的配置文件获取属性值 (支持操作系统环境变量)
System.setProperty("JUNIT_CONF", "sybnuitl_test");
// or java -jar -DJUNIT_CONF=sybnuitl_test
String value4 = getValue("value3@{JUNIT_CONF}.properties");