在 Spring 项目中,如果使用了 Spring 的事务管理的话。
默认的事务级别都在类,这个级别的,这就导致了,如果在循环中对数据进行处理的话,如果循环不结束,事务是不会提交的。
如果出现了事务堆积的情况,大概率就会锁表,然后整个服务抛出异常。
如下面的代码:
public void assignMlsListingUid() {
List<MlsListing> mlsListingList = mlsListingRepository.findAllByUidIsNull();
// Loop MlsListing to get UID assigned
for (MlsListing mlsListing : mlsListingList) {
try {
MlsListingCtx mlsListingCtx = ListingUtils.listingDeserialization(mlsListing.getMlsCtx());
String uid = mlsListing.getUid();
String addressOneLine = mlsListingCtx.getAddress().getAddressOneLine();
Listing listing = listingRepository.findDistinctFirstByAddressOneLineEqualsIgnoreCase(addressOneLine);
if (ObjectUtils.isNotEmpty(listing)) {
uid = listing.getUid();
} else {
uid = UUID.randomUUID().toString();
listing = new Listing();
listing.setAddressOneLine(addressOneLine);
listing.setUid(uid);
listing.setDateCreate(new Date());
listing.setDateUpdate(new Date());
listingRepository.save(listing);
}
mlsListing.setUid(uid);
mlsListing.setDateUpdate(new Date());
mlsListingRepository.save(mlsListing);
} catch (JsonProcessingException e) {
log.error("Parse Mls-Listing Ctx Error", e);
mlsListingRepository.delete(mlsListing);
}
}
}
这个方法,在循环执行完成之前是不会提交事务的。
上面的代码只要部署到服务器上,一旦需要处理的量稍微大一点点,肯定锁表。
解决办法
解决办法就是把循环从 Services 层中拿出来。
放到另外一层,这样的话就能够在循环中进行提交。