并发问题(竞争条件)

时间:2013-12-12 16:05:37

标签: java sql oracle merge prepared-statement

我甚至不确定如何标题这个问题

我有以下方法可以正常工作,但这里有一个竞争条件,问题如下:

MSISDN表中的mobile_number存在唯一约束。

如果提交了包含相同移动电话号码的MULTIPLE(两个或更多)上传,并且它在MSISDN表中不存在,并且上传工作人员在同一时间接收提交,则以下MERGE将在最后一次失败试图犯下的人。

我的问题是如何解决上述问题?

如果失败一次,我可以选择重试,或者删除mobile_number上的唯一约束。但我正在寻找更好的解决方案。代码如下:

protected static void batchInsertIntoMSISDN(DBAccessor dba, String tablename) throws Exception {

        logger.log(Level.INFO, String.format("batch insert into MSISDN STARTED for tableName %s", tablename));

        String sql = "MERGE INTO MSISDN M\n"+
                "      USING  "+tablename +" s\n " +
                " ON (m.mobile_number = s.mobile_number) \n"+
                " WHEN NOT MATCHED \n"+
                "   THEN \n"+
                "       INSERT ( m.id, m.mobile_number,m.state,m.created_date,m.state_updated_date,m.carrier_id ) \n"+
                "       VALUES (MSISDN_ID_SEQ.NEXTVAL,s.mobile_number,'ACTIVE',SYSDATE,SYSDATE,s.carrier_id) where s.mobile_number is not null \n";

        Connection connection = dba.getConnection();
        PreparedStatement stmt = connection.prepareStatement(sql);
        try {
            logger.info("SQL :: "+sql);
            int resultCount = stmt. executeUpdate();

            logger.log(Level.INFO, String.format("Merge into MSISDN SUCCEEDED (%d rows) for tableName %s", resultCount, tablename));
        }
        catch (Exception ex) {
            logger.log(Level.SEVERE, String.format("Merge into MSISDN FAILED for tableName %s", tablename), ex);
            throw ex;
        }
        finally {
            if (stmt != null){
                stmt.close();
            }
        }
    }

非常感谢提前

1 个答案:

答案 0 :(得分:0)

解决问题的最佳方法是使用以下代码:

String sql = "MERGE INTO MSISDN M\n"+
            "      USING  (SELECT mobile_number, carrier_id FROM "+ tablename +" GROUP BY mobile_number, carrier_id) s\n " +
            " ON (m.mobile_number = s.mobile_number) \n"+
            " WHEN NOT MATCHED \n"+
            "   THEN \n"+
            "       INSERT ( m.id, m.mobile_number,m.state,m.created_date,m.state_updated_date,m.carrier_id ) \n"+
            "       VALUES (MSISDN_ID_SEQ.NEXTVAL,s.mobile_number,'ACTIVE',SYSDATE,SYSDATE,s.carrier_id) where s.mobile_number is not null \n";

我不知道如何分配运营商ID,但如果您总是拥有mobile_number和carrier_id的一个组合,那么使用此代码就不会出现重复问题。

如果可以接收mobile_number和carrier_id的不同组合,那么你必须处理你的应用程序规则,我的意思是你想要保存哪些运营商ID? ¿为什么?,¿什么规则会管理这个决定?

这可以指导您决定代码。