spring @Transactional 注解事务不生效解决

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

 

posted @ 2018-09-05 10:29  light-zhang  阅读(11852)  评论(3编辑  收藏  举报