事情是这样的,今天上线了项目的一个功能,主要是用于将服务器机器和集群和关联在一起,然后数据不仅有刚输入的,还有旧平台中老系统的数据,旧平台的数据 有一个字段是存在但是一直没有填入的,大概是型号的意思,我在尝试新数据的时候都没有问题,但是当用到这个模块,对老平台的数据进行修改的时候,就出来了大岔子。这个问题虽然造成的后果不是很严重(执行更新的系统组人员发现更新了几条数据之后 不仅程序出错,而且原本数据丢失),但是我觉得反映的问题挺大的。
代码:
String[] idArgs = ids.split( ",");
String[] strSnArgs = strSns.split( "," ,40);
String[] strPnArgs = strPns.split( "," ,40);
String[] strMTArgs = strMTs.split( "," ,40);
String[] strIPArgs = strIPs.split( "," ,40);
String[] strNameArgs = strNames.split( ",",40 );
String updateTime = DateTools.getFullNowDateTime();
String updateUserId = controllerUtil.currentUser().getStrAccount();
int idLength = idArgs.length;
try {
//1、切断这个集群id对应的主机信息上的相关联系,一共有两个约束,一个约束是将集群的uuid输入到了主机表的clusterId的字段当中,另一个约束是yf_cluster_host这张表
String clusterId = yfClusterInfo.getId();
String clusterInfoId = yfClusterInfo.getStrClusterId();
int clearRes = yfOsInfoService.clearClusterId( clusterId );
yfOsInfoService.clearClusterHost(clusterInfoId);
//2、重新对该集群id绑定主机信息
for (int i = 0 ;i <idArgs.length;i++){
yfOsInfoService.updateClusterId(idArgs[i], clusterId );
String clusterHostId = UUIDUtil.getUUID();
int res2 = yfClusterInfoService.createClusterHost(clusterHostId,clusterInfoId,strIPArgs[i],strSnArgs[i],strPnArgs[i],strMTArgs[i],strNameArgs[i],i,updateTime,updateUserId,idArgs[i]);
System.out.println(res2);
}
//3、更新集群其他字段的信息
yfClusterInfoService.update(yfClusterInfo);
ajaxObject.setMessage("修改成功");
}catch (Exception e){
e.printStackTrace();
ajaxObject.setStatusCode(AjaxObject.STATUS_CODE_FAILURE);
ajaxObject.setMessage("程序出错,修改失败");
}
命名承接了旧平台的命名,类似于项目组的规范,俺知道不对劲。
在split那块,原本我写的是单纯的split(),没有加进limit参数,要说为啥,因为之前没注意这个东西。然后之所以新数据没问题,因为StrPn这个字段如果是新输入的数据是一般都有的,但是问题就出在StrPn在旧平台的数据里啥也不是,于是我拼接之后的strPns就拼了个寂寞。然后Split就开始发挥作用了
split()在面对最后一个或几个对象是 "" 的时候会默认不识别,但只要最后一个不是 "",就一定识别
于是我这个字段识别出来的字符串数组就悲催的变为长度0的数组了,后面调用StrPnArgs[i] 就百分百会报越界异常。
解决方法就是给split加上一个limit,这个长度是你规定的一个最大值或者是-1,-1就是会帮你自动切分的。
那么为什么我的数据会被清空,因为我之前还写了个憨憨函数把它东西先清空了,然后重新放进去的。
可是我记得我之前 如果没有执行成功的话,是会回滚的啊,怎么这个东西就执行进去了。
于是我去看了一下项目的事务设置。
<tx:advice id="txAdvice" transaction-manager="mybatisTransactionManager">
<tx:attributes>
<tx:method name="*" rollback-for="Exception" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
emmm,好像没问题。
然后经别人点拨了一下,我第一步,第二步属于的是同个业务逻辑,却放在了两个方法里头去写,那这时候第二个方法出问题了,第一个方法它肯定不回滚啊。我之所以变成这样写,是因为 创建联系的这个方法是我早就写好的,清除的这个操作是针对update的业务逻辑后面加的,我同个业务逻辑分两块写,就导致了出错了之后,一个方法被执行进去,另一个方法回滚。
最后的解决方法就是该做的业务逻辑一整套都写一个方法里头,防止它出毛病,把service和dao里头顺序改一下加进去就行。
害~