]> source.dussan.org Git - sonarqube.git/commitdiff
Improve usage of JDBC batch mode when deleting a project from UI
authorSimon Brandhof <simon.brandhof@gmail.com>
Mon, 5 Mar 2012 22:23:14 +0000 (23:23 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Mon, 5 Mar 2012 22:23:14 +0000 (23:23 +0100)
sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java

index 3a262e92f191111dcb6f750df42032c9613cf6fc..14792e2c12b50f636dd0932043d09b8eb3cb8fa5 100644 (file)
@@ -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<Long> 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<Long> 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<Long> 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<Long> snapshotIds, final PurgeMapper mapper) {
+  private void deleteSnapshots(final List<Long> 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<Long> snapshotIds, final PurgeMapper mapper) {
+  private void purgeSnapshots(final List<Long> 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();
   }
 
   /**
index 3231b9c225e69e77a912a0929f7fc69237eb36ac..2deacdd4600ee7fcf7449cfa45c0809f37f68961 100644 (file)
@@ -80,4 +80,6 @@ public interface PurgeMapper {
   List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithEvents(long resourceId);
 
   List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithoutEvents(long resourceId);
+
+  List<Long> selectResourceIdsByRootId(long rootProjectId);
 }
index 931b6e953f09f42ff02f9ac4bfae29d9e8113fc5..1a58d70d02dc2814a3f25c932dbc696289dadac7 100644 (file)
@@ -72,7 +72,7 @@
     select id from projects where root_id=#{id} and scope='PRJ'
   </select>
 
-  <select id="selectResourceTreeIdsByRootId" resultType="long" parameterType="long">
+  <select id="selectResourceIdsByRootId" resultType="long" parameterType="long">
     select id from projects where root_id=#{id} or id=#{id}
   </select>
 
index 7cd74d9f51115c6c31f2cae77d3d918139a3ac02..2df27e177c249a9ae76615b779039e791e9861f4 100644 (file)
@@ -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();