#608105 : added batch support for SQLDeleteClause and SQLUpdateClause

This commit is contained in:
Timo Westkämper 2010-08-24 18:13:22 +00:00
parent 073fe111d0
commit 320d110618
4 changed files with 137 additions and 23 deletions

View File

@ -8,7 +8,9 @@ package com.mysema.query.sql.dml;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -43,7 +45,11 @@ public class SQLDeleteClause extends AbstractSQLClause implements DeleteClause<S
private final RelationalPath<?> entity;
private final QueryMetadata metadata = new DefaultQueryMetadata();
private final List<QueryMetadata> batches = new ArrayList<QueryMetadata>();
private QueryMetadata metadata = new DefaultQueryMetadata();
private transient String queryString;
public SQLDeleteClause(Connection connection, SQLTemplates templates, RelationalPath<?> entity) {
this(connection, new Configuration(templates), entity);
@ -59,6 +65,12 @@ public class SQLDeleteClause extends AbstractSQLClause implements DeleteClause<S
metadata.addFlag(new QueryFlag(position, flag));
return this;
}
public SQLDeleteClause addBatch() {
batches.add(metadata);
metadata = new DefaultQueryMetadata();
return this;
}
protected void close(PreparedStatement stmt) {
try {
@ -67,19 +79,52 @@ public class SQLDeleteClause extends AbstractSQLClause implements DeleteClause<S
throw new QueryException(e);
}
}
private PreparedStatement createStatement() throws SQLException{
PreparedStatement stmt;
if (batches.isEmpty()){
SQLSerializer serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForDelete(metadata, entity);
queryString = serializer.toString();
logger.debug(queryString);
stmt = connection.prepareStatement(queryString);
setParameters(stmt, serializer.getConstants(), Collections.<Param<?>,Object>emptyMap());
}else{
SQLSerializer serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForDelete(batches.get(0), entity);
queryString = serializer.toString();
logger.debug(queryString);
// add first batch
stmt = connection.prepareStatement(queryString);
setParameters(stmt, serializer.getConstants(), Collections.<Param<?>,Object>emptyMap());
stmt.addBatch();
// add other batches
for (int i = 1; i < batches.size(); i++){
serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForDelete(batches.get(i), entity);
setParameters(stmt, serializer.getConstants(), Collections.<Param<?>,Object>emptyMap());
stmt.addBatch();
}
}
return stmt;
}
@Override
public long execute() {
SQLSerializer serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForDelete(metadata, entity);
String queryString = serializer.toString();
logger.debug(queryString);
PreparedStatement stmt = null;
try {
stmt = connection.prepareStatement(queryString);
setParameters(stmt, serializer.getConstants(), Collections.<Param<?>,Object>emptyMap());
return stmt.executeUpdate();
stmt = createStatement();
if (batches.isEmpty()){
return stmt.executeUpdate();
}else{
long rv = 0;
for (int i : stmt.executeBatch()){
rv += i;
}
return rv;
}
} catch (SQLException e) {
throw new QueryException("Caught " + e.getClass().getSimpleName() + " for " + queryString, e);
} finally {

View File

@ -48,9 +48,15 @@ public class SQLUpdateClause extends AbstractSQLClause implements UpdateClause<
private final RelationalPath<?> entity;
private final List<Pair<Path<?>,?>> updates = new ArrayList<Pair<Path<?>,?>>();
private final List<QueryMetadata> batchMetadata = new ArrayList<QueryMetadata>();
private final List<List<Pair<Path<?>,?>>> batchUpdates = new ArrayList<List<Pair<Path<?>,?>>>();
private List<Pair<Path<?>,?>> updates = new ArrayList<Pair<Path<?>,?>>();
private final QueryMetadata metadata = new DefaultQueryMetadata();
private QueryMetadata metadata = new DefaultQueryMetadata();
private transient String queryString;
public SQLUpdateClause(Connection connection, SQLTemplates templates, RelationalPath<?> entity) {
this(connection, new Configuration(templates), entity);
@ -66,7 +72,14 @@ public class SQLUpdateClause extends AbstractSQLClause implements UpdateClause<
metadata.addFlag(new QueryFlag(position, flag));
return this;
}
public SQLUpdateClause addBatch() {
batchUpdates.add(updates);
batchMetadata.add(metadata);
updates = new ArrayList<Pair<Path<?>,?>>();
metadata = new DefaultQueryMetadata();
return this;
}
protected void close(PreparedStatement stmt) {
try {
@ -76,18 +89,51 @@ public class SQLUpdateClause extends AbstractSQLClause implements UpdateClause<
}
}
@Override
public long execute() {
SQLSerializer serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForUpdate(metadata, entity, updates);
String queryString = serializer.toString();
logger.debug(queryString);
PreparedStatement stmt = null;
try {
private PreparedStatement createStatement() throws SQLException{
PreparedStatement stmt;
if (batchUpdates.isEmpty()){
SQLSerializer serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForUpdate(metadata, entity, updates);
queryString = serializer.toString();
logger.debug(queryString);
stmt = connection.prepareStatement(queryString);
setParameters(stmt, serializer.getConstants(), Collections.<Param<?>,Object>emptyMap());
return stmt.executeUpdate();
}else{
SQLSerializer serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForUpdate(batchMetadata.get(0), entity, batchUpdates.get(0));
queryString = serializer.toString();
logger.debug(queryString);
// add first batch
stmt = connection.prepareStatement(queryString);
setParameters(stmt, serializer.getConstants(), Collections.<Param<?>,Object>emptyMap());
stmt.addBatch();
// add other batches
for (int i = 1; i < batchUpdates.size(); i++){
serializer = new SQLSerializer(configuration.getTemplates(), true);
serializer.serializeForUpdate(batchMetadata.get(i), entity, batchUpdates.get(i));
setParameters(stmt, serializer.getConstants(), Collections.<Param<?>,Object>emptyMap());
stmt.addBatch();
}
}
return stmt;
}
@Override
public long execute() {
PreparedStatement stmt = null;
try {
stmt = createStatement();
if (batchUpdates.isEmpty()){
return stmt.executeUpdate();
}else{
long rv = 0;
for (int i : stmt.executeBatch()){
rv += i;
}
return rv;
}
} catch (SQLException e) {
throw new QueryException("Caught " + e.getClass().getSimpleName() + " for " + queryString, e);
} finally {

View File

@ -27,7 +27,7 @@ public abstract class DeleteBaseTest extends AbstractBaseTest{
private void reset() throws SQLException{
delete(survey).where(survey.name.isNotNull()).execute();
Connections.getStatement().execute("insert into survey values (1, 'Hello World')");
insert(survey).values(1, "Hello World").execute();
}
@Before
@ -47,5 +47,16 @@ public abstract class DeleteBaseTest extends AbstractBaseTest{
assertEquals(0, delete(survey).where(survey.name.eq("XXX")).execute());
assertEquals(count, delete(survey).execute());
}
@Test
public void batch() throws SQLException{
insert(survey).values(2, "A").execute();
insert(survey).values(3, "B").execute();
SQLDeleteClause delete = delete(survey);
delete.where(survey.name.eq("A")).addBatch();
delete.where(survey.name.eq("B")).addBatch();
assertEquals(2, delete.execute());
}
}

View File

@ -16,6 +16,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.mysema.query.sql.dml.SQLUpdateClause;
import com.mysema.query.types.Path;
public abstract class UpdateBaseTest extends AbstractBaseTest{
@ -84,5 +85,16 @@ public abstract class UpdateBaseTest extends AbstractBaseTest{
long count = query().from(survey).count();
assertEquals(count, update(survey).set(survey.name, null).execute());
}
@Test
public void batch() throws SQLException{
insert(survey).values(2, "A").execute();
insert(survey).values(3, "B").execute();
SQLUpdateClause update = update(survey);
update.set(survey.name, "AA").where(survey.name.eq("A")).addBatch();
update.set(survey.name, "BB").where(survey.name.eq("B")).addBatch();
assertEquals(2, update.execute());
}
}