From: Simon Brandhof Date: Mon, 5 Mar 2012 22:23:14 +0000 (+0100) Subject: Improve usage of JDBC batch mode when deleting a project from UI X-Git-Tag: 2.14~9 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=97180251f9a1809046d02a641cb125e2b4d1ece8;p=sonarqube.git Improve usage of JDBC batch mode when deleting a project from UI --- diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java index 3a262e92f19..14792e2c12b 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java @@ -73,7 +73,7 @@ public class PurgeDao { .setIslast(false) .setStatus(new String[]{"U"}) .setRootProjectId(project.getId()); - deleteSnapshots(query, purgeMapper); + deleteSnapshots(query, session, purgeMapper); session.commit(); } } @@ -97,16 +97,16 @@ public class PurgeDao { .setIslast(false) .setScopes(scopesWithoutHistoricalData) .setRootSnapshotId(projectSnapshotId); - deleteSnapshots(query, purgeMapper); + deleteSnapshots(query, session, purgeMapper); session.commit(); } PurgeSnapshotQuery query = PurgeSnapshotQuery.create().setRootSnapshotId(projectSnapshotId).setNotPurged(true); - purgeSnapshots(query, purgeMapper); + purgeSnapshots(query, session, purgeMapper); session.commit(); // must be executed at the end for reentrance - purgeSnapshots(PurgeSnapshotQuery.create().setId(projectSnapshotId).setNotPurged(true), purgeMapper); + purgeSnapshots(PurgeSnapshotQuery.create().setId(projectSnapshotId).setNotPurged(true), session, purgeMapper); session.commit(); } } @@ -143,45 +143,94 @@ public class PurgeDao { final PurgeVendorMapper vendorMapper = session.getMapper(PurgeVendorMapper.class); try { deleteProject(rootProjectId, session, mapper, vendorMapper); - session.commit(); return this; } finally { MyBatis.closeQuietly(session); } } - private void deleteProject(final long rootProjectId, final SqlSession session, final PurgeMapper mapper, final PurgeVendorMapper vendorMapper) { + private void deleteProject(long rootProjectId, SqlSession session, PurgeMapper mapper, PurgeVendorMapper vendorMapper) { List childrenIds = mapper.selectProjectIdsByRootId(rootProjectId); for (Long childId : childrenIds) { deleteProject(childId, session, mapper, vendorMapper); } - session.select("org.sonar.core.purge.PurgeMapper.selectResourceTreeIdsByRootId", rootProjectId, new ResultHandler() { - public void handleResult(ResultContext context) { - Long resourceId = (Long) context.getResultObject(); - if (resourceId != null) { - deleteResource(resourceId, mapper, vendorMapper); - } - } - }); + List resourceIds = mapper.selectResourceIdsByRootId(rootProjectId); + deleteResources(resourceIds, session, mapper, vendorMapper); + session.commit(); } - void deleteResource(final long resourceId, final PurgeMapper mapper, final PurgeVendorMapper vendorMapper) { - deleteSnapshots(PurgeSnapshotQuery.create().setResourceId(resourceId), mapper); + @VisibleForTesting + void deleteResources(List resourceIds, SqlSession session, PurgeMapper mapper, PurgeVendorMapper vendorMapper) { + // Note : do not merge the delete statements into a single loop of resource ids. It's + // voluntarily grouped by tables in order to benefit from JDBC batch mode. + // Batch requests can only relate to the same PreparedStatement. - // possible optimization: filter requests according to resource scope - mapper.deleteResourceLinks(resourceId); - mapper.deleteResourceProperties(resourceId); - mapper.deleteResourceIndex(resourceId); - mapper.deleteResourceGroupRoles(resourceId); - mapper.deleteResourceUserRoles(resourceId); - mapper.deleteResourceManualMeasures(resourceId); - vendorMapper.deleteResourceReviewComments(resourceId); - vendorMapper.deleteResourceActionPlansReviews(resourceId); - mapper.deleteResourceReviews(resourceId); - mapper.deleteResourceActionPlans(resourceId); - mapper.deleteResourceEvents(resourceId); - mapper.deleteResource(resourceId); + for (Long resourceId : resourceIds) { + deleteSnapshots(PurgeSnapshotQuery.create().setResourceId(resourceId), session, mapper); + } + + // possible missing optimization: filter requests according to resource scope + + for (Long resourceId : resourceIds) { + mapper.deleteResourceLinks(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceProperties(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceIndex(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceGroupRoles(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceUserRoles(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceManualMeasures(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + vendorMapper.deleteResourceReviewComments(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + vendorMapper.deleteResourceActionPlansReviews(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceReviews(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceActionPlans(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResourceEvents(resourceId); + } + session.flushStatements(); + + for (Long resourceId : resourceIds) { + mapper.deleteResource(resourceId); + } + session.flushStatements(); } @VisibleForTesting @@ -196,7 +245,7 @@ public class PurgeDao { final SqlSession session = mybatis.openBatchSession(); try { final PurgeMapper mapper = session.getMapper(PurgeMapper.class); - deleteSnapshots(mapper.selectSnapshotIds(query), mapper); + deleteSnapshots(mapper.selectSnapshotIds(query), session, mapper); session.commit(); return this; @@ -206,65 +255,94 @@ public class PurgeDao { } @VisibleForTesting - void deleteSnapshots(final PurgeSnapshotQuery query, final PurgeMapper mapper) { - deleteSnapshots(mapper.selectSnapshotIds(query), mapper); + void deleteSnapshots(final PurgeSnapshotQuery query, final SqlSession session, final PurgeMapper mapper) { + deleteSnapshots(mapper.selectSnapshotIds(query), session, mapper); } - private void deleteSnapshots(final List snapshotIds, final PurgeMapper mapper) { + private void deleteSnapshots(final List snapshotIds, final SqlSession session, final PurgeMapper mapper) { for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotDependencies(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotDuplications(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotEvents(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotMeasureData(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotMeasures(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotSource(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotViolations(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshot(snapshotId); } + + session.flushStatements(); } @VisibleForTesting - void purgeSnapshots(final PurgeSnapshotQuery query, final PurgeMapper mapper) { - purgeSnapshots(mapper.selectSnapshotIds(query), mapper); + void purgeSnapshots(final PurgeSnapshotQuery query, final SqlSession session, final PurgeMapper mapper) { + purgeSnapshots(mapper.selectSnapshotIds(query), session, mapper); } - private void purgeSnapshots(final List snapshotIds, final PurgeMapper mapper) { + private void purgeSnapshots(final List snapshotIds, final SqlSession session, final PurgeMapper mapper) { // note that events are not deleted for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotDependencies(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotDuplications(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotSource(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotViolations(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotWastedMeasures(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.deleteSnapshotMeasuresOnQualityModelRequirements(snapshotId); } + session.flushStatements(); + for (Long snapshotId : snapshotIds) { mapper.updatePurgeStatusToOne(snapshotId); } + session.flushStatements(); } /** diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java index 3231b9c225e..2deacdd4600 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java @@ -80,4 +80,6 @@ public interface PurgeMapper { List selectPurgeableSnapshotsWithEvents(long resourceId); List selectPurgeableSnapshotsWithoutEvents(long resourceId); + + List selectResourceIdsByRootId(long rootProjectId); } diff --git a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml index 931b6e953f0..1a58d70d02d 100644 --- a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml @@ -72,7 +72,7 @@ select id from projects where root_id=#{id} and scope='PRJ' - select id from projects where root_id=#{id} or id=#{id} diff --git a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java index 7cd74d9f511..2df27e177c2 100644 --- a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java @@ -29,6 +29,7 @@ import org.sonar.core.persistence.DaoTestCase; import org.sonar.core.persistence.MyBatis; import org.sonar.core.resource.ResourceDao; +import java.util.Arrays; import java.util.List; import static org.hamcrest.Matchers.is; @@ -54,7 +55,7 @@ public class PurgeDaoTest extends DaoTestCase { SqlSession session = getMyBatis().openSession(); try { // this method does not commit and close the session - dao.deleteSnapshots(PurgeSnapshotQuery.create().setId(5L), session.getMapper(PurgeMapper.class)); + dao.deleteSnapshots(PurgeSnapshotQuery.create().setId(5L), session, session.getMapper(PurgeMapper.class)); session.commit(); } finally { @@ -80,7 +81,7 @@ public class PurgeDaoTest extends DaoTestCase { SqlSession session = getMyBatis().openSession(); try { - dao.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session.getMapper(PurgeMapper.class)); + dao.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session, session.getMapper(PurgeMapper.class)); // the above method does not commit and close the session session.commit(); @@ -98,9 +99,9 @@ public class PurgeDaoTest extends DaoTestCase { SqlSession session = getMyBatis().openSession(); try { - dao.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session.getMapper(PurgeMapper.class)); + dao.purgeSnapshots(PurgeSnapshotQuery.create().setId(1L), session, session.getMapper(PurgeMapper.class)); -// the above method does not commit and close the session + // the above method does not commit and close the session session.commit(); } finally { @@ -171,7 +172,7 @@ public class PurgeDaoTest extends DaoTestCase { setupData("shouldDeleteResource"); SqlSession session = getMyBatis().openSession(); try { - dao.deleteResource(1L, session.getMapper(PurgeMapper.class), session.getMapper(PurgeVendorMapper.class)); + dao.deleteResources(Arrays.asList(1L), session, session.getMapper(PurgeMapper.class), session.getMapper(PurgeVendorMapper.class)); // the above method does not commit and close the session session.commit();