工作中遇到的问题总结
面试的时候经常会问,讲讲你在工作中遇到的问题,对于没有经验的人来说确实不知道说哪些,我在此把自己遇到的问题写下来,给自己做一下总结,也给大家做一些参考。
1、Mybatis的配置文件xml中,配置了重复的命名空间
经常在新增dao接口之后,把之前的xml文件拷贝过来改一改,但是有一次忘记改nameplace这个标签了,导致出现了问题。
问题描述:
在启动项目的时候,控制台会一直打印下面的信息,项目永远不会启动,因为不报错所以很难发现问题所在。
[DEBUG] 2020-05-20 10:32:34,696 org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [D:\work\CTTQ_SRM\branches\2.6\cdc\cdc-mid\target\cdc-mid-0.0.1-SNAPSHOT\WEB-INF\classes\com\midea\scc\performance\dao\TspPefScoreInputDao.xml]'
[DEBUG] 2020-05-20 10:32:34,711 org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [D:\work\CTTQ_SRM\branches\2.6\cdc\cdc-mid\target\cdc-mid-0.0.1-SNAPSHOT\WEB-INF\classes\com\midea\scc\performance\dao\TspPefSupplyDifficultCalTmpCuxKKDao.xml]'
[DEBUG] 2020-05-20 10:32:34,728 org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [D:\work\CTTQ_SRM\branches\2.6\cdc\cdc-mid\target\cdc-mid-0.0.1-SNAPSHOT\WEB-INF\classes\com\midea\scc\performance\dao\TspPefTemplateDao.xml]'
[DEBUG] 2020-05-20 10:32:34,745 org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [D:\work\CTTQ_SRM\branches\2.6\cdc\cdc-mid\target\cdc-mid-0.0.1-SNAPSHOT\WEB-INF\classes\com\midea\scc\performance\dao\TspSysSimpleResourceAuthorizeCuxKKDao.xml]'
[DEBUG] 2020-05-20 10:32:34,764 org.mybatis.spring.SqlSessionFactoryBean - Parsed mapper file: 'file [D:\work\CTTQ_SRM\branches\2.6\cdc\cdc-mid\target\cdc-mid-0.0.1-SNAPSHOT\WEB-INF\classes\com\midea\scc\purchase\dao\DeliveryMaterialConfigCuxKKDao.xml]'
2、从数据库查询对象,条件相同,每次得到的都会是同一个对象。
如标题,需要对这个对象设置不同的属性并保存到list结合中,最后解析成json格式。
问题描述:
由于list中添加的多个对象都是一个对象,在解析json时会被解析成下面的情况:
@Test
public void test1() {
// 存储集合
ArrayList<One> ones = new ArrayList<>();
// 引用对象
One one = new One();
one.setName("test");
// 将同一个对象添加到集合中
ones.add(one);
ones.add(one);
// 使用FastJson将集合转换成Json字符串
String json = JSON.toJSONString(ones);
System.out.println(json); // 打印Json结果:[{"name":"test"},{"$ref":"$[0]"}]
}
解决方案:
如果查到的对象是同一个,应该使用apache的工具类BeanUtils中的copyProperties来复制一个新的对象再进行操作。
3、在对集合遍历移除元素时,使用for循环报错
问题描述:
下面这段代码执行后报错:Java ConcurrentModificationException
for (ReceiveDetailReq receiveDetailReq : orderDetailReqlList) {
if (!sapFaileList.contains(receiveDetailReq.getId())) {
orderDetailReqlList.remove(receiveDetailReq);
}
}
解决方案:
改用迭代器就ok了。
Iterator<ReceiveDetailReq> receiveDetailReqIterator = orderDetailReqlList.iterator();
while (receiveDetailReqIterator.hasNext()) {
if (!sapFaileList.contains(receiveDetailReqIterator.next().getId())) {
receiveDetailReqIterator.remove();
}
}
4、使用迭代器遍历集合报错NoSuchElementException
问题描述:
下面这段代码执行后报错:java.util.NoSuchElementException
final Iterator iterator = list.iterator();
while (iterator.hasNext()) {
if ("f".equals(iterator.next())) {
System.out.println(iterator.next());
}
}
解决方案:
iterator.next在迭代器遍历中只能出现一回,若多次出现就会报错,查看源码如图:
代码更改如下即可:
final Iterator iterator = list.iterator();
while (iterator.hasNext()) {
final Object next = iterator.next();
if ("f".equals(next)) {
System.out.println(next);
}
}
5、使用Mybatis从数据库查询列表不需要对结果做非空校验
代码优化:
- 使用Mybatis从数据库查询列表,使用List或Set接收的话,不需要对接收结果做非空校验。如果查询到的数据为空,默认会时空集合而不是null。
- 如果使用的时Map或对象接收的话会出现null,需要做非空校验。
示例代码:
List<SrmPurOrderDetail> orderDetailList = purOrderDetailDao.selOrderDetailsByOrderNo(order.getOrderNo());
// 这块直接遍历即可
for (SrmPurOrderDetail detail : orderDetailList) {
......
}
6、Mybatis批量插入,数据量过大导致效率太慢
问题描述:
由于需要保证两个应用的数据一致性,做了一个同步数据库表的接口,同步的这张表数据有1.8W多,再使用mybatis的批量插入时,耗时将近20分钟,这是不能容忍的。
解决方案:
在批量插入的时候,每次插入的条数保证在500条左右,全部1.8W条数据插入用时不到1分钟。
7、数据量大的for循环内不要调用查询数据库、其他应用接口
问题描述:
项目中接口响应时间很慢,通过排查发现其中一个for循环内调用了查询数据库的方法,当时的for循环数据大概有100多条。同样在优化另一个接口的时候,是在for循环中调用的其他应用的dubble接口。
解决方案:
在for循环外层先把需要的数据批量查询出来,在for循环内通过程序来过滤出需要的数据即可。