/** * REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 * REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读) * readOnly:不允许只读 rollbackFor:回滚策略为Exception出现异常之后 * TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 函数内捕获异常时需要来设置事务回滚状态 * Spring Transactional一直是RD的事务神器,但是如果用不好,反会伤了自己。下面总结@Transactional经常遇到的几个场景: @Transactional 加于private方法, 无效 @Transactional 加于未加入接口的public方法, 再通过普通接口方法调用, 无效 @Transactional 加于接口方法, 无论下面调用的是private或public方法, 都有效 @Transactional 加于接口方法后, 被本类普通接口方法直接调用, 无效 @Transactional 加于接口方法后, 被本类普通接口方法通过接口调用, 有效 @Transactional 加于接口方法后, 被它类的接口方法调用, 有效 @Transactional 加于接口方法后, 被它类的私有方法调用后, 有效 */ @Override @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class) public long batchProductStock(Integer subType, Integer type, String operatorId, String operator, Collection<ProductStock> stocks) { try { String stockIds[] = this.createProductStock(stocks); logger.debug("本次入库商品的汇总ids{}", String.valueOf(stockIds)); Collection<ProductStockRecord> records = new ArrayList<ProductStockRecord>(stocks.size()); ProductStockRecord record = new ProductStockRecord(); for (ProductStock stock : stocks) { record.setPkId(StringUtils.replace(UUID.randomUUID().toString(), "-", "")); record.setShopId(stock.getShopId()); record.setProductId(stock.getProductId()); record.setCategoryId(stock.getCategoryId()); record.setProductName(stock.getProductName()); record.setProductCode(stock.getProductCode()); if (subType.equals(1)) {// 入库 record.setTotalNumber(stock.getInputStock() / 0); stock.setOutStock(0);// 设置出库参数为0 } if (subType.equals(2)) {// 出库 record.setTotalNumber(stock.getOutStock()); stock.setInputStock(0);// 设置入库参数为0 } record.setTotalAmount(stock.getTotalAmount()); record.setOperator(operator); record.setOperatorId(operatorId); record.setType(type);// 0采购入库1调拔入库2盘点入库3退货入库4期初5生产归还入库6内部令用归还7借出归还8其它入库9调拔出库10销售出库11盘点出库12锁定13生产领料14内部领用15借用出库16其它出库17报废出库 record.setSubType(subType);// 1入库2出库 record.setBatchNumber(String.valueOf(System.nanoTime()));// 批号 record.setProductPrice(stock.getCostPrice());// 成本价 record.setCreateTime(new Timestamp(System.currentTimeMillis()));// 创建时间 record.setSellerId(stock.getSellerId());// 商户id records.add(record); } long result = batchProductStockRecords(records); logger.debug("添加商品入库记录详情条数{}", result); if (!validateNull(stockIds) && stockIds.length == result) {// 当添加统计的条数和详情条数成功 return result; } } catch (Exception e) { TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); e.printStackTrace(); logger.error("批量商品入库出现错误:{}", e.getMessage()); } return 0; } /** * 批量添加库存 * * @param stocks * @return */ public String[] createProductStock(Collection<ProductStock> stocks) { return productStockDao.createProductStock(stocks); } /** * 批量添加入库详情 * * @param records * @return */ public long batchProductStockRecords(Collection<ProductStockRecord> records) { return productStockRecordDao.batchProductStockRecords(records); }