然而当时不懂这些啊,就是记得好像是因为in后面的数据太多了,超过1000就奇差无比,我记得当时百度了N多资料,让我整出了for循环每1000条就and拼接的玩法,像这样:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numberList.size(); i++) {
if ((i % 1000) == 0 && i > 0) {
sb.deleteCharAt(sb.length() - 1);
// resolved ORA-01795 problem.
sb.append(") OR number IN ( '" + numberList.get(i) + "',");
} else {
sb.append("'" + numberList.get(i) + "',");
}
}
// delete the last comma
sb.deleteCharAt(sb.length() - 1);
String sql = "select *,*from table where number in ("
+ sb.toString()
+ ") and ....";
很傻吧,但是最近做的项目却用到了这里的一段,这也再次提醒我积累的重要性,首先,这次的需求大概是处理照片的,涉及到文件io操作这块确实很痛苦啊,哦跑偏题了,回到正题,还记得我遇到的第一个坑就是在for循环里一遍一遍操作数据库,所以我现在写插入都是这样的:
dateMapper.batchInsert(new ArrayList<data>() {{add(oneData); }});
/**
* 批量插入
*
* @param dataList
*/
void batchInsert(@Param("dataList") List<data> dataList);
<insert id="batchInsert">
INSERT INTO table (ID,*,CREATE_TIME, MODIFY_TIME)
VALUES
<foreach collection="dataList" item="data" index="index" separator=",">
(
#{data.*},
now(),
now()
)
</foreach>
</insert>
看到没,就算只一条一条插入我也写成支持批量插入的:)
,事务 事务.png
,分布式事务等问题,就不细说了,说回批量的实现,借助了一开始的代码,实现如下:
@Async
public void add( List<data> dataAddList) {
if (CollectionUtils.isNotEmpty(dataAddList)) {
StringBuilder sb = new StringBuilder();
int size = dataAddList.size();
for (int i = 0; i < dataAddList.size(); i++) {
sb.append(dataAddList.get(i).getId());
sb.append(",");
if (i > 0 && (i % 50) == 0) {
size -= 50;
int batch = i / 50;
batchAdd(dataAddList.subList((batch - 1) * 50, batch * 50), sb.deleteCharAt(sb.length() - 1).toString());
sb = new StringBuilder();
}
if (size < 50) {
for (int j = 0; j < size - 1; j++) {
sb.append(dataAddList.get(i + j).getId());
sb.append(",");
}
batchAdd( dataAddList.subList(i, dataAddList.size()), sb.deleteCharAt(sb.length() - 1).toString());
return;
}
}
}
}
顺便安利几个项目里用到的io方法吧,真的感觉还挺好用的:
//移动文件到目录
FileUtils.moveFileToDirectory(file, directory, true);
// 追加写入by FileUtils
FileUtils.writeStringToFile(file, string, "utf-8", true);
打开一个文件流
FileInputStream Input = FileUtils.openInputStream(file);
然后是因为发送文件只能发送MultipartFile 就用测试mock了一个发过去
MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain", IOUtils.toByteArray(Input));
String md5 = DigestUtils.md5Hex(multipartFile.getBytes());
//获取MD5,注意此处有坑,md5Hex(input)会导致mock失败只能先关流再重新开流才行,而如果先mock再获取MD5的话会导致获取的MD5值完全一致,所以我一开始是很蠢的开一遍流再关流再重新开流来解决的,后来发现用multipartFile.getBytes()替代input可以解决这个问题,至于网上的用这种input复用方法个人实验发现完全没卵用:
inputStream复用.png
说起积累,忍不住在最后闲聊几句,很多的时候,我们大部分程序员大部分时间在写些简单重复的代码,谁会天天写高并发,大数据处理,分布式架构等等高大上的东西呢?,这些大部分只是在面试的时候会问到,真写过有几个人写过呢,我相信写增删改查的时间一定占据了我们大部分时间。那就有很大培训班,网课,之类的给你安利各种高大上的技术,牛逼的架构什么的,其实我倒是觉得写好每一行代码才是正经事,每写一行代码想想若干年后可能会有人对你的代码一番吐槽,我相信你就不会为了赶时间完成任务而那么随意了,我记得潘爱民演讲的时候拿出他几十年写的一小段C语言代码,那已经成为微软底层的一部分了,我们现在在电脑上浏览这篇文章,我在编辑的时候就会用到这行代码。这是对细节上的讲究,谈回积累,很多人写了N多代码却没有任何复盘和总结,实现过就完了,下次再遇到类似希求又写一遍,有意思吗?不是说鼓励大家存工作的代码,事实上每个程序员签劳动合同的同时都会签订保密协议,在第二家公司的时候也见到过有傻子把公司代码上传到GitHub上被告到法院的例子,但这不代表你不能记笔记,不能总结,不能留存复用自己凝思苦想的结果,事实上,我在简书上写这些,也就是趁自己有空把自己做过的项目需求总结一下,回顾一下,积累一下,我觉得花半天时间总结一下做了一两个星期或几个月的项目绝对比在电脑面前看半天网课老师吹牛逼来的实际有用得多。建议各位可以像这样
第*周(yyyy.MM.dd-yyyy.MM.dd):双周
周一(yyyy.MM.dd):
周二(yyyy.MM.dd):
周三(yyyy.MM.dd):
周四(yyyy.MM.dd):
周五(yyyy.MM.dd):
写份工作日志(自己用,有日报或周报要求的也可以写)每天一句话,离职的时候,我都是直接这个一给就交接了,希望程序员路上与君共勉!
网友评论