I use Hibernate ORM and PostgreSQL in my application, and sometimes i use batch operations.
And at first I didn't understand why in the logs with size of the batch = 25, 25 queries are generated, and at first thought that it does not work correctly.
But after that I looked at the source code of the pg driver and found the following lines in the PgStatement class:
public int[] executeBatch() throws SQLException {
this.checkClosed();
this.closeForNextExecution();
if (this.batchStatements != null && !this.batchStatements.isEmpty()) {
this.transformQueriesAndParameters();
//confuses next line, because we have array of identical queries
Query[] queries = (Query[])this.batchStatements.toArray(new Query[0]);
ParameterList[] parameterLists =
(ParameterList[])this.batchParameters.toArray(new ParameterList[0]);
this.batchStatements.clear();
this.batchParameters.clear();
and in PgPreparedStatement class
public void addBatch() throws SQLException {
checkClosed();
if (batchStatements == null) {
batchStatements = new ArrayList<Query>();
batchParameters = new ArrayList<ParameterList>();
}
batchParameters.add(preparedParameters.copy());
Query query = preparedQuery.query;
//confuses next line
if (!(query instanceof BatchedQuery) || batchStatements.isEmpty()) {
batchStatements.add(query);
}
}
I noticed that it turns out that if the size of the batch goes 25,
25 queries are sent with the parameters attached to them.
Logs of the database confirm this, for example:
2017-12-06 01:22:08.023 MSK [18402] postgres@buzzfactory СООБЩЕНИЕ: выполнение S_3: BEGIN
2017-12-06 01:22:08.024 MSK [18402] postgres@buzzfactory СООБЩЕНИЕ: выполнение S_4: select nextval ('tests_id_seq')
2017-12-06 01:22:08.041 MSK [18402] postgres@buzzfactory СООБЩЕНИЕ: выполнение S_2: insert into tests (name, id) values ($1, $2)
2017-12-06 01:22:08.041 MSK [18402] postgres@buzzfactory ПОДРОБНОСТИ: параметры: $1 = 'test', $2 = '1'
2017-12-06 01:22:08.041 MSK [18402] postgres@buzzfactory СООБЩЕНИЕ: выполнение S_2: insert into tests (name, id) values ($1, $2)
2017-12-06 01:22:08.041 MSK [18402] postgres@buzzfactory ПОДРОБНОСТИ: параметры: $1 = 'test', $2 = '2'
...
x23 queries with parameters
...
2017-12-06 01:22:08.063 MSK [18402] postgres@buzzfactory СООБЩЕНИЕ: выполнение S_5: COMMIT
But i thought one query must be executed with an array of 25 parameters.
Or I don't understand how batch inserts work with a prepared statement?
Why duplicate one query n times?
After all, i tried to debug my queries on this place
if (!(query instanceof BatchedQuery) || batchStatements.isEmpty()) {
and noticed that my queries are always instance of SimpleQuery instead of BatchedQuery. Maybe this is the solution to the problem? Information about BatchedQuery i couldn't find
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…