通过@@ Transactional注释进行事务管理

时间:2019-03-26 11:42:30

标签: database spring spring-boot jpa transactions

我有一个要求,我必须在一个表中插入记录并在另一个表中更新记录。

在插入和更新之前,我必须完成100条记录。 但是,如果任何记录由于插入或更新中的任何错误而失败,则仅应回滚该记录而不是其他记录。这意味着如果有100条记录并且60条获得成功,而61条由于任何错误而失败,则仅应回滚61条记录其他60条记录。

我正在使用Spring boot JPA和@Transactional注释。但是如果将此注释放在我的方法开始处,那么如果发生任何错误,它将回滚所有记录。

我在下面附上我的代码。请提出如何实现此目的。 在下面的代码中,我有persistentRecord()方法,其中包含我所有的插入和更新代码。我没有使用@Transactional注释来标记此方法,而在下面的方法中使用@Transactional注释进行了注释


        logger.debug("insertSalesTargetData method called of service class");
        String userid = (String) webSession.getAttribute("username");
        logger.debug("Userid :" + userid);
        HashMap<String, String> persistRecordStatus = new HashMap<String, String>();
        Query qCountCheck = em.createNativeQuery(QueryConstant.CHECK_SALES_TARGET_DATA_QUERY);
        List<Object> existingRecordList = null;
        persistRecordStatus.put("TOTAL_RECORD", String.valueOf(xlsRowslist.size()));
        int failedRecordCount = 0;
        int successRecordCount = 0;
        for (int i = 0; i < xlsRowslist.size(); i++) {
            ArrayList rowList = xlsRowslist.get(i);
            // try {
            double weekNoDouble = Double.parseDouble((String) rowList.get(0));// Week No
            String fromDate = (String) rowList.get(1);// fromDate
            String toDate = (String) rowList.get(2);// toDate
            double catCodeDouble = Double.parseDouble((String) rowList.get(3));// catCode
            int catCode = (int) catCodeDouble;
            int weekNo = (int) weekNoDouble;
            String target = (String) rowList.get(4);// target

            String salesGoalId = fromDate + toDate + catCode;
            salesGoalId = salesGoalId.replace("-", "");

            // Check if the sales goal id already exist in the database or not
            qCountCheck.setParameter(1, salesGoalId);// SALES_GOAL_ID
            existingRecordList = qCountCheck.getResultList();
            logger.debug("Count List Size " + existingRecordList.size());
            if (existingRecordList != null && existingRecordList.size() > 0) {
                if (existingRecordList.get(0) != null) {
                    BigDecimal row = (BigDecimal) existingRecordList.get(0);
                    // try {
                    logger.debug("Persisting record no  " + i);
                    persistRecord(row, salesGoalId, target, fromDate, toDate, userid, catCode, weekNo);
                    logger.debug("Record no  " + i + " persisted");
                    persistRecordStatus.put("SUCCESS_RECORD", String.valueOf(successRecordCount++));
                    /*
                     * } catch (Exception e) { persistRecordStatus.put("FAILED_RECORD",
                     * String.valueOf(failedRecordCount++)); }
                     */

                }
            } else {
                persistRecordStatus.put("FAILED_RECORD",String.valueOf(failedRecordCount++));
            }
            /*
             * } catch (Exception e) { logger.debug("Exception in processing record no " + i
             * + " " + e.toString()); persistRecordStatus.put("FAILED_RECORD",
             * String.valueOf(failedRecordCount++)); }
             */

        }
        return persistRecordStatus;
    }

1 个答案:

答案 0 :(得分:1)

您要进行某种批量更新吗?

在批处理中,您将所有涉及的东西(例如输入记录,错误代码等)放在错误存储库中,以供某些用户随后查看,以处理“失败”。然后您将其与所有“成功”更新一起提交。

或者,将每个插入/更新对放入自己的事务中。 (并且仍然可以选择,如果您的DBMS /事务框架支持保存点,则在每个插入/更新对之后获取一个保存点,并在失败时回滚到最后一个保存点,然后提交(并找出一种不会丢失其余40个未处理条目的方法)您的输入)。无论哪种情况,如果遇到性能问题,请不要抱怨。

在事务批处理中,这两种方式都没有。