From 1e207b3b6de3382938c710a7c6135be4ce849219 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Mon, 9 Jul 2012 11:36:01 +0200 Subject: [PATCH] SONAR-3437 Use MyBatis instead of Hibernate to improve batch insert --- .../sonar/batch/index/MeasurePersister.java | 130 +++++++++------ .../batch/index/MeasurePersisterTest.java | 67 ++++---- .../{shared.xml => data.xml} | 0 .../index/MeasurePersisterTest/empty.xml | 2 + ...ldAddDelayedMeasureSeveralTimes-result.xml | 9 + .../shouldDelaySaving-result.xml | 10 +- .../shouldInsertMeasure-result.xml | 8 +- .../shouldInsertRuleMeasure-result.xml | 9 + ...aySavingWithDatabaseOnlyMeasure-result.xml | 15 -- .../org/sonar/core/persistence/MyBatis.java | 8 + .../sonar/core/persistence/H2Database.java | 1 + .../sonar/api/database/model/MeasureDto.java | 156 ++++++++++++++++++ .../database/model/MeasureModelMapper.java | 26 +++ .../model/MeasureModelMapper-oracle.xml | 46 ++++++ .../api/database/model/MeasureModelMapper.xml | 43 +++++ 15 files changed, 423 insertions(+), 107 deletions(-) rename sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/{shared.xml => data.xml} (100%) create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertRuleMeasure-result.xml delete mode 100644 sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldNotDelaySavingWithDatabaseOnlyMeasure-result.xml create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureDto.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModelMapper.java create mode 100644 sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper-oracle.xml create mode 100644 sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper.xml diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java index 3b967d89e38..c270e2fd071 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java @@ -19,13 +19,16 @@ */ package org.sonar.batch.index; +import org.sonar.api.database.model.MeasureDto; + import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.SetMultimap; import org.apache.commons.lang.math.NumberUtils; +import org.apache.ibatis.session.SqlSession; import org.slf4j.LoggerFactory; -import org.sonar.api.database.DatabaseSession; import org.sonar.api.database.model.MeasureModel; +import org.sonar.api.database.model.MeasureModelMapper; import org.sonar.api.database.model.Snapshot; import org.sonar.api.measures.Measure; import org.sonar.api.measures.Metric; @@ -35,20 +38,21 @@ import org.sonar.api.resources.ResourceUtils; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.utils.SonarException; +import org.sonar.core.persistence.MyBatis; import java.util.Collection; import java.util.Map; public final class MeasurePersister { - private final DatabaseSession session; + private final MyBatis mybatis; private final ResourcePersister resourcePersister; private final RuleFinder ruleFinder; private final MemoryOptimizer memoryOptimizer; private final SetMultimap unsavedMeasuresByResource = LinkedHashMultimap.create(); private boolean delayedMode = false; - public MeasurePersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder, MemoryOptimizer memoryOptimizer) { - this.session = session; + public MeasurePersister(MyBatis mybatis, ResourcePersister resourcePersister, RuleFinder ruleFinder, MemoryOptimizer memoryOptimizer) { + this.mybatis = mybatis; this.resourcePersister = resourcePersister; this.ruleFinder = ruleFinder; this.memoryOptimizer = memoryOptimizer; @@ -64,17 +68,13 @@ public final class MeasurePersister { return; } - if (measure.getId() != null) { // update - MeasureModel model = session.reattach(MeasureModel.class, measure.getId()); - model = mergeModel(measure, model); - - model.save(session); - memoryOptimizer.evictDataMeasure(measure, model); - } else if (shouldPersistMeasure(resource, measure)) { // insert - Snapshot snapshot = resourcePersister.getSnapshotOrFail(resource); - MeasureModel model = createModel(measure).setSnapshotId(snapshot.getId()); - - model.save(session); + MeasureModel model = null; + if (measure.getId() != null) { + model = update(measure); + } else if (shouldPersistMeasure(resource, measure)) { + model = insert(measure, resourcePersister.getSnapshotOrFail(resource)); + } + if (model != null) { memoryOptimizer.evictDataMeasure(measure, model); } } @@ -114,57 +114,91 @@ public final class MeasurePersister { public void dump() { LoggerFactory.getLogger(getClass()).debug("{} measures to dump", unsavedMeasuresByResource.size()); - Map> map = unsavedMeasuresByResource.asMap(); - for (Map.Entry> entry : map.entrySet()) { - Resource resource = entry.getKey(); - Snapshot snapshot = resourcePersister.getSnapshot(entry.getKey()); - for (Measure measure : entry.getValue()) { - if (shouldPersistMeasure(resource, measure)) { - MeasureModel model = createModel(measure).setSnapshotId(snapshot.getId()); - model.save(session); + SqlSession session = mybatis.openSession(); + try { + MeasureModelMapper mapper = session.getMapper(MeasureModelMapper.class); + + Map> map = unsavedMeasuresByResource.asMap(); + for (Map.Entry> entry : map.entrySet()) { + Resource resource = entry.getKey(); + Snapshot snapshot = resourcePersister.getSnapshot(entry.getKey()); + for (Measure measure : entry.getValue()) { + if (shouldPersistMeasure(resource, measure)) { + mapper.insert(new MeasureDto(model(measure).setSnapshotId(snapshot.getId()))); + } } } + session.commit(); + } finally { + MyBatis.closeQuietly(session); } - session.commit(); unsavedMeasuresByResource.clear(); } - private MeasureModel createModel(Measure measure) { - return mergeModel(measure, new MeasureModel()); - } - - private MeasureModel mergeModel(Measure measure, MeasureModel merge) { - merge.setMetricId(measure.getMetric().getId()); // we assume that the index has updated the metric - merge.setDescription(measure.getDescription()); - merge.setData(measure.getData()); - merge.setAlertStatus(measure.getAlertStatus()); - merge.setAlertText(measure.getAlertText()); - merge.setTendency(measure.getTendency()); - merge.setVariationValue1(measure.getVariation1()); - merge.setVariationValue2(measure.getVariation2()); - merge.setVariationValue3(measure.getVariation3()); - merge.setVariationValue4(measure.getVariation4()); - merge.setVariationValue5(measure.getVariation5()); - merge.setUrl(measure.getUrl()); - merge.setCharacteristic(measure.getCharacteristic()); - merge.setPersonId(measure.getPersonId()); + private MeasureModel model(Measure measure) { + MeasureModel model = new MeasureModel(); + model.setMetricId(measure.getMetric().getId()); // we assume that the index has updated the metric + model.setDescription(measure.getDescription()); + model.setData(measure.getData()); + model.setAlertStatus(measure.getAlertStatus()); + model.setAlertText(measure.getAlertText()); + model.setTendency(measure.getTendency()); + model.setVariationValue1(measure.getVariation1()); + model.setVariationValue2(measure.getVariation2()); + model.setVariationValue3(measure.getVariation3()); + model.setVariationValue4(measure.getVariation4()); + model.setVariationValue5(measure.getVariation5()); + model.setUrl(measure.getUrl()); + model.setCharacteristic(measure.getCharacteristic()); + model.setPersonId(measure.getPersonId()); if (measure.getValue() != null) { - merge.setValue(measure.getValue().doubleValue()); + model.setValue(measure.getValue().doubleValue()); } else { - merge.setValue(null); + model.setValue(null); } if (measure instanceof RuleMeasure) { RuleMeasure ruleMeasure = (RuleMeasure) measure; - merge.setRulePriority(ruleMeasure.getSeverity()); + model.setRulePriority(ruleMeasure.getSeverity()); if (ruleMeasure.getRule() != null) { Rule ruleWithId = ruleFinder.findByKey(ruleMeasure.getRule().getRepositoryKey(), ruleMeasure.getRule().getKey()); if (ruleWithId == null) { throw new SonarException("Can not save a measure with unknown rule " + ruleMeasure); } - merge.setRuleId(ruleWithId.getId()); + model.setRuleId(ruleWithId.getId()); } } - return merge; + return model; + } + + private MeasureModel insert(Measure measure, Snapshot snapshot) { + MeasureModel model = model(measure).setSnapshotId(snapshot.getId()); + + SqlSession session = mybatis.openSession(); + try { + MeasureModelMapper mapper = session.getMapper(MeasureModelMapper.class); + mapper.insert(new MeasureDto(model)); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + + return model; + } + + private MeasureModel update(Measure measure) { + MeasureModel model = model(measure); + model.setId(measure.getId()); + + SqlSession session = mybatis.openSession(); + try { + MeasureModelMapper mapper = session.getMapper(MeasureModelMapper.class); + mapper.update(new MeasureDto(model)); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + + return model; } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java index 4d13104ba42..3bb6707129a 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java @@ -27,12 +27,14 @@ import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.measures.Metric; import org.sonar.api.measures.PersistenceMode; +import org.sonar.api.measures.RuleMeasure; import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.JavaPackage; import org.sonar.api.resources.Project; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import java.util.List; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.rules.RulePriority; +import org.sonar.core.persistence.AbstractDaoTestCase; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.any; @@ -41,7 +43,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public class MeasurePersisterTest extends AbstractDbUnitTestCase { +public class MeasurePersisterTest extends AbstractDaoTestCase { public static final int PROJECT_SNAPSHOT_ID = 3001; public static final int PACKAGE_SNAPSHOT_ID = 3002; @@ -49,6 +51,7 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { public static final int COVERAGE_METRIC_ID = 2; private MeasurePersister measurePersister; + private RuleFinder ruleFinder = mock(RuleFinder.class); private ResourcePersister resourcePersister = mock(ResourcePersister.class); private MemoryOptimizer memoryOptimizer = mock(MemoryOptimizer.class); private Project project = new Project("foo"); @@ -63,30 +66,36 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { when(resourcePersister.getSnapshot(project)).thenReturn(projectSnapshot); when(resourcePersister.getSnapshot(aPackage)).thenReturn(packageSnapshot); - measurePersister = new MeasurePersister(getSession(), resourcePersister, null, memoryOptimizer); + measurePersister = new MeasurePersister(getMyBatis(), resourcePersister, ruleFinder, memoryOptimizer); } @Test public void shouldInsertMeasure() { - setupData("shared"); + setupData("empty"); Measure measure = new Measure(ncloc()).setValue(1234.0); measurePersister.saveMeasure(project, measure); checkTables("shouldInsertMeasure", "project_measures"); + verify(memoryOptimizer).evictDataMeasure(eq(measure), any(MeasureModel.class)); } @Test - public void shouldRegisterPersistedMeasureToMemoryOptimizer() { - Measure measure = new Measure(ncloc()).setValue(1234.0); + public void shouldInsertRuleMeasure() { + setupData("empty"); + + Rule rule = Rule.create("pmd", "key"); + when(ruleFinder.findByKey("pmd", "key")).thenReturn(rule); + + Measure measure = new RuleMeasure(ncloc(), rule, RulePriority.MAJOR, 1).setValue(1234.0); measurePersister.saveMeasure(project, measure); - verify(memoryOptimizer).evictDataMeasure(eq(measure), any(MeasureModel.class)); + checkTables("shouldInsertRuleMeasure", "project_measures"); } @Test public void shouldUpdateMeasure() { - setupData("shared"); + setupData("data"); Measure measure = new Measure(coverage()).setValue(12.5).setId(1L); measurePersister.saveMeasure(project, measure); @@ -96,8 +105,11 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { @Test public void shouldAddDelayedMeasureSeveralTimes() { - Measure measure = new Measure(ncloc()).setValue(200.0); + setupData("empty"); + + Measure measure = new Measure(ncloc()); + measure.setValue(200.0); measurePersister.setDelayedMode(true); measurePersister.saveMeasure(project, measure); @@ -105,19 +117,18 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { measurePersister.saveMeasure(project, measure); measurePersister.dump(); - List coverageMeasures = getSession().getResults(MeasureModel.class, "snapshotId", PROJECT_SNAPSHOT_ID, "metricId", 1); - assertThat(coverageMeasures).onProperty("value").containsExactly(300.0); + checkTables("shouldAddDelayedMeasureSeveralTimes", "project_measures"); } @Test public void shouldDelaySaving() { - setupData("shared"); + setupData("empty"); measurePersister.setDelayedMode(true); measurePersister.saveMeasure(project, new Measure(ncloc()).setValue(1234.0)); measurePersister.saveMeasure(aPackage, new Measure(ncloc()).setValue(50.0)); - assertThat(getSession().getResults(MeasureModel.class, "metricId", 1)).isEmpty(); + assertEmptyTables("project_measures"); measurePersister.dump(); checkTables("shouldDelaySaving", "project_measures"); @@ -125,42 +136,40 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { @Test public void shouldNotDelaySavingWithDatabaseOnlyMeasure() { - setupData("shared"); + setupData("empty"); measurePersister.setDelayedMode(true); - measurePersister.saveMeasure(project, new Measure(ncloc()).setValue(1234.0).setPersistenceMode(PersistenceMode.DATABASE)); // database - measurePersister.saveMeasure(aPackage, new Measure(ncloc()).setValue(50.0)); // database + memory + measurePersister.saveMeasure(project, new Measure(ncloc()).setValue(1234.0).setPersistenceMode(PersistenceMode.DATABASE)); + measurePersister.saveMeasure(aPackage, new Measure(ncloc()).setValue(50.0)); - checkTables("shouldNotDelaySavingWithDatabaseOnlyMeasure", "project_measures"); + checkTables("shouldInsertMeasure", "project_measures"); } @Test public void shouldNotSaveBestValues() { - Measure measure = new Measure(coverage()).setValue(0.0); - assertThat(MeasurePersister.shouldPersistMeasure(aFile, measure)).isTrue(); - - measure = new Measure(coverage()).setValue(75.8); - assertThat(MeasurePersister.shouldPersistMeasure(aFile, measure)).isTrue(); - - measure = new Measure(coverage()).setValue(100.0); - assertThat(MeasurePersister.shouldPersistMeasure(aFile, measure)).isFalse(); + assertThat(MeasurePersister.shouldPersistMeasure(aFile, new Measure(coverage()).setValue(0.0))).isTrue(); + assertThat(MeasurePersister.shouldPersistMeasure(aFile, new Measure(coverage()).setValue(75.8))).isTrue(); + assertThat(MeasurePersister.shouldPersistMeasure(aFile, new Measure(coverage()).setValue(100.0))).isFalse(); } @Test public void shouldNotSaveBestValueMeasuresInDelayedMode() { + setupData("empty"); + measurePersister.setDelayedMode(true); measurePersister.saveMeasure(aFile, new Measure(coverage()).setValue(100.0)); - assertThat(getSession().getResults(MeasureModel.class, "metricId", COVERAGE_METRIC_ID, "snapshotId", FILE_SNAPSHOT_ID)).isEmpty(); + assertEmptyTables("project_measures"); measurePersister.dump(); - assertThat(getSession().getResults(MeasureModel.class, "metricId", COVERAGE_METRIC_ID, "snapshotId", FILE_SNAPSHOT_ID)).isEmpty(); + assertEmptyTables("project_measures"); } @Test public void shouldNotSaveMemoryOnlyMeasures() { Measure measure = new Measure("ncloc").setPersistenceMode(PersistenceMode.MEMORY); + assertThat(MeasurePersister.shouldPersistMeasure(aPackage, measure)).isFalse(); } diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/data.xml similarity index 100% rename from sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shared.xml rename to sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/data.xml diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml new file mode 100644 index 00000000000..fb0854fccbe --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/empty.xml @@ -0,0 +1,2 @@ + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml new file mode 100644 index 00000000000..a9d69262af3 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldAddDelayedMeasureSeveralTimes-result.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml index f0ac513c87d..3aecc2ea40e 100644 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml @@ -1,19 +1,13 @@ - - - - - - - + + + + diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldNotDelaySavingWithDatabaseOnlyMeasure-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldNotDelaySavingWithDatabaseOnlyMeasure-result.xml deleted file mode 100644 index 1cd6e6d10c4..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldNotDelaySavingWithDatabaseOnlyMeasure-result.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java index d051fe69422..fc2c07a1821 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java @@ -19,6 +19,12 @@ */ package org.sonar.core.persistence; +import org.sonar.api.database.model.MeasureDto; + +import org.sonar.api.database.model.MeasureModel; + +import org.sonar.api.database.model.MeasureModelMapper; + import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.ibatis.builder.xml.XMLMapperBuilder; @@ -98,6 +104,7 @@ public class MyBatis implements BatchComponent, ServerComponent { loadAlias(conf, "UserRole", UserRoleDto.class); loadAlias(conf, "Widget", WidgetDto.class); loadAlias(conf, "WidgetProperty", WidgetPropertyDto.class); + loadAlias(conf, "MeasureDto", MeasureDto.class); loadMapper(conf, ActiveDashboardMapper.class); loadMapper(conf, AuthorMapper.class); @@ -123,6 +130,7 @@ public class MyBatis implements BatchComponent, ServerComponent { loadMapper(conf, UserMapper.class); loadMapper(conf, WidgetMapper.class); loadMapper(conf, WidgetPropertyMapper.class); + loadMapper(conf, MeasureModelMapper.class); sessionFactory = new SqlSessionFactoryBuilder().build(conf); return this; diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/H2Database.java b/sonar-core/src/test/java/org/sonar/core/persistence/H2Database.java index bc893b4bd75..55db7c2ed94 100644 --- a/sonar-core/src/test/java/org/sonar/core/persistence/H2Database.java +++ b/sonar-core/src/test/java/org/sonar/core/persistence/H2Database.java @@ -57,6 +57,7 @@ public class H2Database implements Database { properties.put("driverClassName", "org.h2.Driver"); properties.put("username", "sonar"); properties.put("password", "sonar"); + // properties.put("url", "jdbc:h2:mem:sonar2;TRACE_LEVEL_SYSTEM_OUT=2"); properties.put("url", "jdbc:h2:mem:sonar2"); // limit to 2 because of Hibernate and MyBatis diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureDto.java b/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureDto.java new file mode 100644 index 00000000000..a0cb386407d --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureDto.java @@ -0,0 +1,156 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.database.model; + +import java.util.Date; + +public class MeasureDto { + private final Long id; + private final Double value; + private final String textValue; + private final Integer tendency; + private final Integer metricId; + private final Integer snapshotId; + private final Integer projectId; + private final String description; + private final Date measureDate; + private final Integer ruleId; + private final Integer rulePriority; + private final String alertStatus; + private final String alertText; + private final Double variationValue1; + private final Double variationValue2; + private final Double variationValue3; + private final Double variationValue4; + private final Double variationValue5; + private final String url; + private final Integer characteristicId; + private final Integer personId; + + // private List measureData = new ArrayList(); + + public MeasureDto(MeasureModel model) { + id = model.getId(); + value = model.getValue(); + textValue = model.getTextValue(); + tendency = model.getTendency(); + metricId = model.getMetricId(); + snapshotId = model.getSnapshotId(); + projectId = model.getProjectId(); + description = model.getDescription(); + measureDate = model.getMeasureDate(); + ruleId = model.getRuleId(); + rulePriority = (null == model.getRulePriority()) ? null : model.getRulePriority().ordinal(); + alertStatus = (null == model.getAlertStatus()) ? null : model.getAlertStatus().name(); + alertText = model.getAlertText(); + variationValue1 = model.getVariationValue1(); + variationValue2 = model.getVariationValue2(); + variationValue3 = model.getVariationValue3(); + variationValue4 = model.getVariationValue4(); + variationValue5 = model.getVariationValue5(); + url = model.getUrl(); + characteristicId = (null == model.getCharacteristic()) ? null : model.getCharacteristic().getId(); + personId = model.getPersonId(); + } + + public Long getId() { + return id; + } + + public Double getValue() { + return value; + } + + public String getTextValue() { + return textValue; + } + + public Integer getTendency() { + return tendency; + } + + public Integer getMetricId() { + return metricId; + } + + public Integer getSnapshotId() { + return snapshotId; + } + + public Integer getProjectId() { + return projectId; + } + + public String getDescription() { + return description; + } + + public Date getMeasureDate() { + return measureDate; + } + + public Integer getRuleId() { + return ruleId; + } + + public Integer getRulePriority() { + return rulePriority; + } + + public String getAlertStatus() { + return alertStatus; + } + + public String getAlertText() { + return alertText; + } + + public Double getVariationValue1() { + return variationValue1; + } + + public Double getVariationValue2() { + return variationValue2; + } + + public Double getVariationValue3() { + return variationValue3; + } + + public Double getVariationValue4() { + return variationValue4; + } + + public Double getVariationValue5() { + return variationValue5; + } + + public String getUrl() { + return url; + } + + public Integer getCharacteristicId() { + return characteristicId; + } + + public Integer getPersonId() { + return personId; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModelMapper.java b/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModelMapper.java new file mode 100644 index 00000000000..615971f3ffe --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModelMapper.java @@ -0,0 +1,26 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.database.model; + +public interface MeasureModelMapper { + void insert(MeasureDto measure); + + void update(MeasureDto measure); +} diff --git a/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper-oracle.xml b/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper-oracle.xml new file mode 100644 index 00000000000..655f4cecc7a --- /dev/null +++ b/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper-oracle.xml @@ -0,0 +1,46 @@ + + + + + + + + select project_measures_seq.NEXTVAL from DUAL + + INSERT INTO project_measures (id, + value, metric_id, snapshot_id, rule_id, text_value, tendency, measure_date, + project_id, alert_status, alert_text, url, description, rule_priority, characteristic_id, variation_value_1, + variation_value_2, variation_value_3, variation_value_4, variation_value_5, person_id) + VALUES (#{id}, + #{value}, #{metricId}, #{snapshotId}, #{ruleId}, #{textValue, jdbcType=VARCHAR}, #{tendency}, + #{measureDate, jdbcType=TIMESTAMP}, #{projectId}, #{alertStatus, jdbcType=VARCHAR}, #{alertText, jdbcType=VARCHAR}, + #{url, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{rulePriority}, #{characteristicId}, #{variationValue1}, + #{variationValue2}, #{variationValue3}, #{variationValue4}, #{variationValue5}, #{personId} + ) + + + + + UPDATE project_measures + SET + value = #{value}, + metric_id = #{metricId}, + rule_id = #{ruleId}, + text_value = #{textValue, jdbcType=VARCHAR}, + tendency = #{tendency}, + alert_status = #{alertStatus, jdbcType=VARCHAR}, + alert_text = #{alertText, jdbcType=VARCHAR}, + url = #{url, jdbcType=VARCHAR}, + description = #{description, jdbcType=VARCHAR}, + rule_priority = #{rulePriority}, + characteristic_id = #{characteristicId}, + variation_value_1 = #{variationValue1}, + variation_value_2 = #{variationValue2}, + variation_value_3 = #{variationValue3}, + variation_value_4 = #{variationValue4}, + variation_value_5 = #{variationValue5}, + person_id = #{personId} + WHERE id = #{id} + + + diff --git a/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper.xml b/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper.xml new file mode 100644 index 00000000000..594674a1b3c --- /dev/null +++ b/sonar-plugin-api/src/main/resources/org/sonar/api/database/model/MeasureModelMapper.xml @@ -0,0 +1,43 @@ + + + + + + + INSERT INTO project_measures ( + value, metric_id, snapshot_id, rule_id, text_value, tendency, measure_date, + project_id, alert_status, alert_text, url, description, rule_priority, characteristic_id, variation_value_1, + variation_value_2, variation_value_3, variation_value_4, variation_value_5, person_id) + VALUES ( + #{value}, #{metricId}, #{snapshotId}, #{ruleId}, #{textValue, jdbcType=VARCHAR}, #{tendency}, + #{measureDate, jdbcType=TIMESTAMP}, #{projectId}, #{alertStatus, jdbcType=VARCHAR}, #{alertText, jdbcType=VARCHAR}, + #{url, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{rulePriority}, #{characteristicId}, #{variationValue1}, + #{variationValue2}, #{variationValue3}, #{variationValue4}, #{variationValue5}, #{personId} + ) + + + + + UPDATE project_measures + SET + value = #{value}, + metric_id = #{metricId}, + rule_id = #{ruleId}, + text_value = #{textValue, jdbcType=VARCHAR}, + tendency = #{tendency}, + alert_status = #{alertStatus, jdbcType=VARCHAR}, + alert_text = #{alertText, jdbcType=VARCHAR}, + url = #{url, jdbcType=VARCHAR}, + description = #{description, jdbcType=VARCHAR}, + rule_priority = #{rulePriority}, + characteristic_id = #{characteristicId}, + variation_value_1 = #{variationValue1}, + variation_value_2 = #{variationValue2}, + variation_value_3 = #{variationValue3}, + variation_value_4 = #{variationValue4}, + variation_value_5 = #{variationValue5}, + person_id = #{personId} + WHERE id = #{id} + + + -- 2.39.5