From 36da250ceb42320d6481986e96a47a9e83da5a56 Mon Sep 17 00:00:00 2001 From: f43nd1r Date: Sun, 24 Jun 2018 20:48:57 +0200 Subject: [PATCH] fix #10 by only using native queries in change processors --- .../LiquibaseChangePostProcessor.java | 17 ++++++++- .../liquibase/change/ReportColumnsChange.java | 27 +++++++++----- .../liquibase/change/StacktraceChange.java | 36 ++++++++++++------- .../java/com/faendir/acra/model/Report.java | 4 --- .../com/faendir/acra/service/DataService.java | 12 +------ 5 files changed, 59 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/faendir/acra/liquibase/LiquibaseChangePostProcessor.java b/src/main/java/com/faendir/acra/liquibase/LiquibaseChangePostProcessor.java index 554bc7d..e09e7f3 100644 --- a/src/main/java/com/faendir/acra/liquibase/LiquibaseChangePostProcessor.java +++ b/src/main/java/com/faendir/acra/liquibase/LiquibaseChangePostProcessor.java @@ -13,10 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.faendir.acra.liquibase; import liquibase.changelog.ChangeSet; +import org.springframework.transaction.annotation.Transactional; + +import javax.persistence.Query; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; /** * @author lukas @@ -29,6 +34,16 @@ public abstract class LiquibaseChangePostProcessor { this.changeId = changeId; } + @Transactional + protected void iterate(Supplier supplier, Consumer consumer) { + int offset = 0; + List list; + while (!(list = supplier.get().setFirstResult(offset).setMaxResults(64).getResultList()).isEmpty()) { + list.forEach(consumer::accept); + offset += list.size(); + } + } + void handle(ChangeSet changeSet) { if (changeId.equals(changeSet.getId())) { afterChange(); diff --git a/src/main/java/com/faendir/acra/liquibase/change/ReportColumnsChange.java b/src/main/java/com/faendir/acra/liquibase/change/ReportColumnsChange.java index c83ae06..daea139 100644 --- a/src/main/java/com/faendir/acra/liquibase/change/ReportColumnsChange.java +++ b/src/main/java/com/faendir/acra/liquibase/change/ReportColumnsChange.java @@ -13,34 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.faendir.acra.liquibase.change; import com.faendir.acra.liquibase.LiquibaseChangePostProcessor; -import com.faendir.acra.model.Report; -import com.faendir.acra.service.DataService; +import org.acra.ReportField; +import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; +import javax.persistence.EntityManager; + /** * @author lukas * @since 01.06.18 */ @Component public class ReportColumnsChange extends LiquibaseChangePostProcessor { - - @NonNull private final DataService dataService; + @NonNull private final EntityManager entityManager; @Autowired - public ReportColumnsChange(@NonNull @Lazy DataService dataService) { + public ReportColumnsChange(@NonNull @Lazy EntityManager entityManager) { super("2018-06-01-add-report-columns"); - this.dataService = dataService; + this.entityManager = entityManager; } @Override protected void afterChange() { - dataService.transformAllReports(Report::initFields); + iterate(() -> entityManager.createNativeQuery("SELECT content FROM report"), o -> { + String content = (String) o; + JSONObject json = new JSONObject(content); + String id = json.getString(ReportField.REPORT_ID.name()); + String brand = json.optString(ReportField.BRAND.name()); + String installationId = json.optString(ReportField.INSTALLATION_ID.name()); + entityManager.createNativeQuery("UPDATE report SET brand = ?1, installation_id = ?2 WHERE id = ?3") + .setParameter(1, brand) + .setParameter(2, installationId) + .setParameter(3, id) + .executeUpdate(); + }); } } diff --git a/src/main/java/com/faendir/acra/liquibase/change/StacktraceChange.java b/src/main/java/com/faendir/acra/liquibase/change/StacktraceChange.java index b602ed5..56f6544 100644 --- a/src/main/java/com/faendir/acra/liquibase/change/StacktraceChange.java +++ b/src/main/java/com/faendir/acra/liquibase/change/StacktraceChange.java @@ -16,8 +16,6 @@ package com.faendir.acra.liquibase.change; import com.faendir.acra.liquibase.LiquibaseChangePostProcessor; -import com.faendir.acra.model.Stacktrace; -import com.faendir.acra.service.DataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.lang.NonNull; @@ -31,30 +29,42 @@ import javax.persistence.EntityManager; */ @Component public class StacktraceChange extends LiquibaseChangePostProcessor { - @NonNull private final DataService dataService; @NonNull private final EntityManager entityManager; @Autowired - public StacktraceChange(@NonNull @Lazy DataService dataService, @NonNull @Lazy EntityManager entityManager) { + public StacktraceChange(@NonNull @Lazy EntityManager entityManager) { super("2018-06-04-add-stacktrace-table"); - this.dataService = dataService; this.entityManager = entityManager; } @Override protected void afterChange() { - dataService.transformAllReports(report -> { - Object[] result = (Object[]) entityManager.createNativeQuery( - "SELECT report.stacktrace, report.version_code, report.version_name, report.bug_id FROM report where report.id = ?1") - .setParameter(1, report.getId()) - .getSingleResult(); + iterate(() -> entityManager.createNativeQuery( + "SELECT stacktrace, version_code, version_name, bug_id, id FROM report"), o -> { + Object[] result = (Object[]) o; String trace = (String) result[0]; int versionCode = (int) result[1]; String versionName = (String) result[2]; int bugId = (int) result[3]; - Stacktrace stacktrace = dataService.findStacktrace(trace) - .orElseGet(() -> new Stacktrace(dataService.findBug(bugId).orElseThrow(IllegalStateException::new), trace, versionCode, versionName)); - report.setStacktrace(stacktrace); + int reportId = (int) result[4]; + Long stacktraceId = (Long) entityManager.createNativeQuery("SELECT id FROM stacktrace WHERE stacktrace = ?1 AND version_code = ?2") + .setParameter(1, trace) + .setParameter(2, versionCode) + .setMaxResults(1) + .getSingleResult(); + if(stacktraceId == null) { + entityManager.createNativeQuery("INSERT INTO stacktrace (bug_id, stacktrace, version_code, version_name) VALUES(?1, ?2, ?3, ?4)") + .setParameter(1, bugId) + .setParameter(2, trace) + .setParameter(3, versionCode) + .setParameter(4, versionName) + .executeUpdate(); + stacktraceId = (Long) entityManager.createNativeQuery("SELECT id FROM stacktrace ORDER BY id DESC").setMaxResults(1).getSingleResult(); + } + entityManager.createNativeQuery("UPDATE report SET stacktrace_id = ?1 WHERE id = ?2") + .setParameter(1, stacktraceId) + .setParameter(2, reportId) + .executeUpdate(); }); } } diff --git a/src/main/java/com/faendir/acra/model/Report.java b/src/main/java/com/faendir/acra/model/Report.java index b73713f..8dca7d1 100644 --- a/src/main/java/com/faendir/acra/model/Report.java +++ b/src/main/java/com/faendir/acra/model/Report.java @@ -62,10 +62,6 @@ public class Report { public Report(@NonNull Stacktrace stacktrace, @NonNull String content) { this.stacktrace = stacktrace; this.content = content; - initFields(); - } - - public final void initFields() { this.id = getJsonObject().getString(ReportField.REPORT_ID.name()); this.date = Utils.getDateFromString(getJsonObject().optString(ReportField.USER_CRASH_DATE.name())); this.userEmail = getJsonObject().optString(ReportField.USER_EMAIL.name()); diff --git a/src/main/java/com/faendir/acra/service/DataService.java b/src/main/java/com/faendir/acra/service/DataService.java index 3377617..851e866 100644 --- a/src/main/java/com/faendir/acra/service/DataService.java +++ b/src/main/java/com/faendir/acra/service/DataService.java @@ -56,6 +56,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.persistence.EntityManager; +import javax.persistence.Query; import javax.validation.constraints.Size; import java.io.IOException; import java.io.Serializable; @@ -338,17 +339,6 @@ public class DataService implements Serializable { return ((JPAQuery) new JPAQuery<>(entityManager)).from(report).where(where).select(select).distinct().orderBy(order.asc()).fetch(); } - @Transactional - public void transformAllReports(Consumer consumer) { - CloseableIterator iterator = new JPAQuery<>(entityManager).from(report).select(report).iterate(); - while (iterator.hasNext()) { - Report report = iterator.next(); - consumer.accept(report); - store(report); - } - iterator.close(); - } - @NonNull public List getStacktraces(@NonNull Bug bug) { return new JPAQuery<>(entityManager).from(stacktrace1).where(stacktrace1.bug.eq(bug)).select(stacktrace1).fetch();