有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java H2 1.4.199 database getGeneratedKeys()返回由另一个insert事务生成的键,或者将来的对象被混淆

我正在使用Java1.8和H21.4.199

我有一个insertRecord(DATA_对象)方法,它将单行插入表中,然后返回生成的此行ID。它实例化一个任务对象,并将其逐个提交到SingleThreadExecutorService上,生成的ID从未来的对象中检索。大多数情况下,它工作得很好。但是,有时会出现这样的情况:

  • 第10行插入已提交给ExecutorService
  • 第11行插入意味着在“已同步”块前面等待提交给ExecutorService
  • 第10行由代码插入,未来返回生成的ID=11
  • 第11行由代码插入,未来返回生成的ID=11

我没有工作和可复制的例子,因为这是一个非常罕见的情况,但它发生了

没有抛出异常,我也不知道这是怎么发生的

下面是代码示例:

private static final ExecutorService singleExecutor = Executors.newSingleThreadExecutor();

private static String insertRecord(DATA_OBJECT dataObject) {
    Future<String> future;
    synchronized (singleExecutor) {
        future = singleExecutor.submit(new Task(dataObject));
    }
    try {
        return future.get();
    } catch (InterruptedException ex) {
        Logger.getLogger(CLASS_NAME.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ExecutionException ex) {
        Logger.getLogger(CLASS_NAME.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private class Task implements Callable<String> {

    private DATA_OBJECT dataObject;

    public Task(DATA_OBJECT dataObject) {
        this.dataObject = dataObject;
    }

    @Override
    public String call() {
        try {
            return execute(dataObject);
        } catch (SQLException ex) {
            Logger.getLogger(CLASS_NAME.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

}

private static String execute(DATA_OBJECT dataObject) {
    Connection conn = Database.getTransactedConnection();
    String lastId = null;
    boolean success = false;
    try (
            PreparedStatement statement = 
                    conn.prepareStatement(
                            "insert into TABLE (COLUMN_NAMES) values (VALUES)", 
                            Statement.RETURN_GENERATED_KEYS
                    )
    ) {
            statement.setString(1, dataObject.STRING_1);
            statement.setString(N, dataObject.STRING_N);
            success = statement.executeUpdate() == 1;
            if (success) {
                try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
                    if (generatedKeys.next()) {
                        lastID = generatedKeys.getString(1);
                    }
                }
            }
    } finally {
        if (success)
            conn.commit();
        else 
            conn.rollback();
        Database.releaseConnection(conn);
    }
    return lastId;
}

我试图找到一种方法来避免100%的这些事件,因为后果是毁灭性的。我该怎么做

导致将来返回标识符的问题可能是什么


共 (0) 个答案