/** * 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); }