Java:如何保持三个对象之间的关系

时间:2013-12-09 03:12:26

标签: java collections tuples

我希望存储三个对象之间的关系列表,其中两个相关对象将仅存在于列表中的一个关系中,第三个是我可以递增的计数。它不是很普遍,但你可以看到我在这里做什么

    public class Transaction implements AutoCloseable {
    private final Connection conn;
    private final Map<String, Map.Entry<PreparedStatement, Integer>> sts = new HashMap<>();

    Transaction(final Connection conn) throws SQLException {
        conn.setAutoCommit(false);
        this.conn = conn;
    }

    <T> void batch(final String st, final List<T> ts,
            final BatchingInstructions<T> bi) throws SQLException {
        final PreparedStatement stat;
        int counter;

        // if statement has already been created, retrieve statement and batch count
        if (sts.containsKey(st)) {
            final Map.Entry<PreparedStatement, Integer> m = sts.get(st);
            stat = m.getKey();
            counter = m.getValue();
        } else {
            // else create statement and batch count
            stat = conn.prepareStatement(getInsert(st));
            counter = 0;
            sts.put(st, // Can't do a new Map.Entry, really
        }

        for (final T t : ts) {
            bi.batch(stat, t);
            stat.addBatch();
            // increment how many times a batch has been added to the statement.
            // execute batch if necessary.
            if (++counter > 5000) {
                stat.executeBatch();
            }
        }

    }

    @Override
    public void close() throws Exception {
        for (final Map.Entry<PreparedStatement, Integer> m : sts.values()) {
            if (m.getValue() > 0) {
                m.getKey().executeBatch();
            }
            m.getKey().close();
        }
        conn.commit();
    }

Guava的表并不完全正常,而且Map<String, Map<Statement, Integer>>也不理想,并且由于需要增加其中一个值而变得复杂(尽管为此我可能会使用此处找到的mutableInt解决方案) Most efficient way to increment a Map value in Java)。

我想知道是否有人知道这个问题的任何直接解决方案,可能在第三方图书馆?


使用接受的答案,我可以让新课做许多其他有用的事情。

class BatchPreparedStatement implements AutoCloseable {
    private final PreparedStatement st;
    private int counter = 0;

    BatchPreparedStatement(final PreparedStatement st) {
        this.st = st;
    }

    <T> void addBatch(final BatchingInstructions<T> bi, final T t)
            throws SQLException {
        bi.batch(st, t);
        st.addBatch();
        executeBatch(10000);
    }

    void executeBatch(final int count) throws SQLException {
        if (counter++ > count) {
            st.executeBatch();
            counter = 0;
        }
    }

    void finished() throws SQLException {
        executeBatch(0);
    }

    @Override
    public void close() throws Exception {
        st.close();
    }
}

3 个答案:

答案 0 :(得分:1)

为什么不创建一个包含Statement,count和处理所有addBatching以及其他杂项活动的Class。

class BatchPreparedStatementHolder {

    private int batchCount;
    private PreparedStatement ps;

    public BatchPreparedStatementHolder(PreparedStatement statement){
        batchCount = 0;
        ps = statment;
    }

    public void addBatch(){
        ps.addBatch();
        // increment how many times a batch has been added to the statement.
        // execute batch if necessary.
        if (++batchCount> 5000) {
            ps.executeBatch();
            batchCount = 0;
        }
    }

    ....

}

答案 1 :(得分:0)

课堂建议非常好,但如果你只需要一些简单的东西,那就有点重。我会使用类似 HashMap 的东西。 (其他语言称这些“词典”)。我没有时间阅读您的所有代码,但看起来您可能正在使用Google地图?

无论如何,您可以将密钥设置为自动递增的值(如在数据库中),并且值可以是,例如其他两个值的元组或数组。有关HashMaps的好建议,请参阅以下链接:

http://java67.blogspot.com/2013/02/10-examples-of-hashmap-in-java-programming-tutorial.html

或者只是创建一个数组,其中索引引用自动递增的函数,而内容是另一个数组?

不确定您需要什么,但这些可能有效!

答案 2 :(得分:0)

不是将Map.Entry保留在地图中,而是可以保留嵌套类..这样很容易处理......就像那样...

class Transaction implements AutoCloseable {
            private final Connection conn;

            class MapValue {
                PreparedStatement p;
                int index ;
                public MapValue(){}
                public MapValue(PreparedStatement p , int i)
                {
                    index= i;
                    this.p=p;
                }
            }
            private final Map<String, MapValue> sts = new HashMap<>();

            Transaction(final Connection conn) throws SQLException {
                conn.setAutoCommit(false);
                this.conn = conn;
            }

            <T> void batch(final String st, final List<T> ts,
                    final BatchingInstructions<T> bi) throws SQLException {
                final PreparedStatement stat;
                int counter;

                // if statement has already been created, retrieve statement and batch count
                if (sts.containsKey(st)) {
                     MapValue  m = sts.get(st);
                    stat = m.p;
                    counter = m.index;
                } else {
                    // else create statement and batch count

                    stat = conn.prepareStatement(getInsert(st));
                    MapValue m = new MapValue(stat, 0);
                    sts.put(st, m);

                }

                for (final T t : ts) {
                    bi.batch(stat, t);
                    stat.addBatch();
                    // increment how many times a batch has been added to the statement.
                    // execute batch if necessary.
                    if (++counter > 5000) {
                        stat.executeBatch();
                    }
                }
                @Override
                public void close() throws Exception {
                    for (final Map.Entry<PreparedStatement, Integer> m : sts.values()) {
                        if (m.getValue() > 0) {
                            m.getKey().executeBatch();
                        }
                        m.getKey().close();
                    }
                    conn.commit();
                }


      }