I'm looking to store a list of relations between three objects, where two of the related objects will each only exist in one relation in the list and the third is a count that I can increment. It's not very generalizable to SO at large, but you can see what I'm doing here
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's Table doesn't exactly work, and a Map<String, Map<Statement, Integer>>
is also not ideal, and it's all complicated by the need to increment one of the values (though for that I'll probably use the mutableInt solution found here Most efficient way to increment a Map value in Java).
I was wondering if anybody knew of any straightforward solutions to this issue, possibly in third party libraries?
Using the accepted answer, I was able to have the new class do a number of other useful things.
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();
}
}