diff --git a/IntegryManagementSystem.ipr b/IntegryManagementSystem.ipr
index 5e51672188..86e5c7673e 100644
--- a/IntegryManagementSystem.ipr
+++ b/IntegryManagementSystem.ipr
@@ -108,6 +108,9 @@
+
+
+
@@ -254,7 +257,7 @@
-
+
@@ -721,7 +724,7 @@
-
+
@@ -867,7 +870,7 @@
-
+
@@ -937,7 +940,7 @@
-
+
@@ -952,7 +955,7 @@
-
+
@@ -1117,6 +1120,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1501,16 +1540,16 @@
-
-
+
+
-
+
-
+
-
+
diff --git a/ems-core/pom.xml b/ems-core/pom.xml
index f03a425393..f945c93764 100644
--- a/ems-core/pom.xml
+++ b/ems-core/pom.xml
@@ -437,6 +437,12 @@
${jackson.version}
+
+ com.alibaba
+ fastjson
+ 2.0.47
+
+
org.springframework
diff --git a/ems-core/src/main/java/it/integry/ems/adapter/BooleanDeserializer.java b/ems-core/src/main/java/it/integry/ems/adapter/BooleanDeserializer.java
index 783d58dee3..7a4cfa77d7 100644
--- a/ems-core/src/main/java/it/integry/ems/adapter/BooleanDeserializer.java
+++ b/ems-core/src/main/java/it/integry/ems/adapter/BooleanDeserializer.java
@@ -37,17 +37,10 @@ public class BooleanDeserializer extends JsonDeserializer {
return Boolean.FALSE;
}
-// if ("N".equalsIgnoreCase(text) || text.length() == 0) {
-// return Boolean.FALSE;
-// }
-//
-// if ("Y".equalsIgnoreCase(text)) {
-// return Boolean.TRUE;
-// }
throw ctxt.weirdStringException("", _valueClass, "only \"true\" or \"false\" recognized");
}
// Otherwise, no can do:
- throw ctxt.mappingException(_valueClass);
+ throw ctxt.instantiationException(_valueClass, "error");
}
}
diff --git a/ems-core/src/main/java/it/integry/ems/controller/EmsController.java b/ems-core/src/main/java/it/integry/ems/controller/EmsController.java
index be28421608..1c293ff97b 100644
--- a/ems-core/src/main/java/it/integry/ems/controller/EmsController.java
+++ b/ems-core/src/main/java/it/integry/ems/controller/EmsController.java
@@ -705,7 +705,7 @@ public class EmsController {
if (ordinaSuPriorita)
entityList = entityPropertyHolder.getEntityChain(entityList, multiDBTransactionManager.getPrimaryConnection());
- Integer prevTransactionGroupId = null;
+ Long prevTransactionGroupId = null;
for (EntityBase entity : entityList) {
entity.setTransactionGroupId(prevTransactionGroupId);
diff --git a/ems-core/src/main/java/it/integry/ems/rules/businessLogic/LoadColliService.java b/ems-core/src/main/java/it/integry/ems/rules/businessLogic/LoadColliService.java
index 3ea2175102..1c24e5a913 100644
--- a/ems-core/src/main/java/it/integry/ems/rules/businessLogic/LoadColliService.java
+++ b/ems-core/src/main/java/it/integry/ems/rules/businessLogic/LoadColliService.java
@@ -27,6 +27,8 @@ import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.*;
+import static it.integry.ems.rules.completing.QueryRules.getSingleValue;
+
@Service
@Scope("request")
public class LoadColliService {
@@ -262,6 +264,16 @@ public class LoadColliService {
dtbDoct.setMtbColt(mtbColt);
}
+ // Acquisizione ID_LOTTO del primo collo da agganciare
+ if (loadDatiFromDB) {
+ query = "SELECT TOP 1 id_lotto FROM mtb_colt ";
+ query = UtilityDB.addwhereCond(query, whereCond, false);
+ Integer idLotto = (Integer) getSingleValue(multiDBTransactionManager.getPrimaryConnection(), query);
+ if (idLotto != null){
+ dtbDoct.setIdLotto(idLotto);
+ }
+ }
+
Stream.of(loadColli.getColli()).forEach(x -> x.setUpdateColliFromDoc(true));
//AGGIUNGERE CAMPI CHE PASSIAMO DA FUORI
@@ -585,7 +597,8 @@ public class LoadColliService {
" dtb_ordr.cod_promo as 'cod_promo', " +
" dtb_ordr.cod_art_for as 'cod_art_for', " +
" mvw_kit.flag_kit as 'articolo_composto', " +
- " IsNull(mvw_colr_sum.cod_jcom, dtb_ordr.cod_jcom) as 'cod_jcom', " +
+ /*" IsNull(mvw_colr_sum.cod_jcom, dtb_ordr.cod_jcom) as 'cod_jcom', " +*/
+ " dtb_ordr.cod_jcom as 'cod_jcom', " +
" IsNull(dtb_ordr.unt_ord2, mtb_aart.unt_mis2) as 'unt_doc2', " +
" IsNull(dtb_ordr.unt_ord3, mtb_aart.unt_mis3) as 'unt_doc3', " +
" mtb_aart.tara_kg as 'tara_kg', " +
@@ -652,7 +665,8 @@ public class LoadColliService {
" mtb_aart.flag_stato, " +
" dtb_ordr.cod_art_for, " +
" mvw_kit.flag_kit, " +
- " IsNull(mvw_colr_sum.cod_jcom, dtb_ordr.cod_jcom), " +
+ /*" IsNull(mvw_colr_sum.cod_jcom, dtb_ordr.cod_jcom), " +*/
+ " dtb_ordr.cod_jcom, " +
" IsNull(dtb_ordr.unt_ord2, mtb_aart.unt_mis2), " +
" IsNull(dtb_ordr.unt_ord3, mtb_aart.unt_mis3), " +
" mtb_aart.tara_kg, " +
diff --git a/ems-core/src/main/java/it/integry/ems/service/EntityProcessor.java b/ems-core/src/main/java/it/integry/ems/service/EntityProcessor.java
index 3c535d6cbc..8fce41c407 100644
--- a/ems-core/src/main/java/it/integry/ems/service/EntityProcessor.java
+++ b/ems-core/src/main/java/it/integry/ems/service/EntityProcessor.java
@@ -498,7 +498,7 @@ public class EntityProcessor {
entities = entityPropertyHolder.getEntityChain(entities, multiDBTransactionManager.getPrimaryDatasource().getConnection());
}
- Integer prevTransactionGroupId = null;
+ Long prevTransactionGroupId = null;
for (int i = 0; i < entities.size(); i++) {
EntityBase entity = entities.get(i);
diff --git a/ems-core/src/main/java/it/integry/ems/sync/AsyncHistoryManager.java b/ems-core/src/main/java/it/integry/ems/sync/AsyncHistoryManager.java
index 1508eab559..a93d555f43 100644
--- a/ems-core/src/main/java/it/integry/ems/sync/AsyncHistoryManager.java
+++ b/ems-core/src/main/java/it/integry/ems/sync/AsyncHistoryManager.java
@@ -1,19 +1,25 @@
package it.integry.ems.sync;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement;
import it.integry.annotations.PostContextConstruct;
import it.integry.ems.datasource.DataSource;
import it.integry.ems.json.JSONObjectMapper;
import it.integry.ems.looper.service.LooperService;
import it.integry.ems.sync.MultiDBTransaction.MultiDBTransactionManager;
+import it.integry.ems.sync.dto.ExportHistoryGroupDTO;
import it.integry.ems.sync.dto.ExportHistoryItemDTO;
import it.integry.ems.sync.dto.ExportHistoryStatusDTO;
import it.integry.ems.sync.dto.PublicationDTO;
import it.integry.ems_model.base.EntityBase;
import it.integry.ems_model.base.EntityPropertyHolder;
+import it.integry.ems_model.entity.StbPublications;
+import it.integry.ems_model.entity.StbPublicationsDetail;
import it.integry.ems_model.entity.StbTransactionLog;
import it.integry.ems_model.types.OperationType;
import it.integry.ems_model.utility.UtilityDB;
import it.integry.ems_model.utility.UtilityLocalDate;
+import javafx.util.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,7 +28,10 @@ import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
@Component
public class AsyncHistoryManager {
@@ -39,27 +48,36 @@ public class AsyncHistoryManager {
private JSONObjectMapper jsonObjectMapper;
//Implement check list like distribuzione
- private final HashMap> currentlyInExecution = new HashMap<>();
+ private final AtomicReference> currentlyInExecutionG = new AtomicReference<>(new ArrayList<>());
@PostContextConstruct
public void init() {
this.looperService.add(this::consumeRetrieveQueue, 10 * 1000, "async-history-read");
- this.looperService.add(this::consumeProcessedQueue, 10 * 1000, "async-history-save");
+ this.looperService.add(this::consumeProcessedQueue, 2 * 1000, "async-history-save");
}
public void addToExportQueue(DataSource dataSource, long groupId, PublicationDTO publication) throws Exception {
- tryAddInExecutionList(groupId, new ExportHistoryItemDTO()
- .setPublicationGroupId(groupId)
- .setPublication(publication)
- .setDataSource(dataSource));
+ tryAddInExecutionList(groupId, dataSource, new ExportHistoryItemDTO()
+ .setPublication(publication));
}
- private void tryAddInExecutionList(long groupId, ExportHistoryItemDTO exportHistoryItemDTO) throws Exception {
- currentlyInExecution.putIfAbsent(groupId, new ArrayList<>());
+ private void tryAddInExecutionList(long groupId, DataSource dataSource, ExportHistoryItemDTO exportHistoryItemDTO) throws Exception {
- List list = currentlyInExecution.get(groupId);
+ ExportHistoryGroupDTO currentlyInExec = currentlyInExecutionG.get().stream()
+ .filter(x -> x.getGroupId() == groupId)
+ .findFirst().orElseGet(() ->
+ {
+ final ExportHistoryGroupDTO exportHistoryGroupDTO = new ExportHistoryGroupDTO()
+ .setDataSource(dataSource)
+ .setGroupId(groupId);
+
+ currentlyInExecutionG.get().add(exportHistoryGroupDTO);
+ return exportHistoryGroupDTO;
+ });
+
+ List list = currentlyInExec.getItems();
final boolean alreadyRegistered = list.stream()
.anyMatch(x -> x.getPublication().getId() == exportHistoryItemDTO.getPublication().getId());
@@ -67,164 +85,181 @@ public class AsyncHistoryManager {
throw new Exception("Il sistema sta già elaborando questa publication");
}
- exportHistoryItemDTO.setTotalItemCount(countExistingItems(exportHistoryItemDTO));
+ currentlyInExec.setTotalItemCount(currentlyInExec.getTotalItemCount() + countExistingItems(dataSource, exportHistoryItemDTO));
list.add(exportHistoryItemDTO);
}
private void consumeRetrieveQueue() {
- final List currentlyInExecutionKeys = new ArrayList<>(currentlyInExecution.keySet());
- for (long currentGroupId : currentlyInExecutionKeys) {
- List entitiesToExport = currentlyInExecution.get(currentGroupId);
+ for (ExportHistoryGroupDTO currentGroup : currentlyInExecutionG.get()) {
+ List entitiesToExport = currentGroup.getItems();
+
+ if (currentGroup.getStartTime() != null)
+ continue;
+
+ currentGroup.setStartTime(UtilityLocalDate.getNowTime());
for (ExportHistoryItemDTO entityToExport : entitiesToExport) {
try {
- internalExportEntity(entityToExport);
+ internalExportEntity(currentGroup, entityToExport);
} catch (Exception ex) {
+ ex.printStackTrace();
logger.error(ex.getMessage(), ex);
}
}
+
+ currentGroup.setCompletedRead(true);
}
}
- private void internalExportEntity(ExportHistoryItemDTO entityHistoryToExport) throws Exception {
+ private void internalExportEntity(ExportHistoryGroupDTO exportHistoryGroup, ExportHistoryItemDTO entityHistoryToExport) throws Exception {
+ if (entityHistoryToExport.getStartDate() == null)
+ entityHistoryToExport.setStartDate(UtilityLocalDate.getNowTime());
+
final Class extends EntityBase> entityClass = entityPropertyHolder.getEntityClassFromTableName(entityHistoryToExport.getPublication().getEntityName());
- try (MultiDBTransactionManager newConnection = new MultiDBTransactionManager(entityHistoryToExport.getDataSource().getProfile())) {
- retrieveEntitiesByChunk(newConnection.getPrimaryConnection(), entityHistoryToExport, entityClass);
+ try (MultiDBTransactionManager newConnection = new MultiDBTransactionManager(exportHistoryGroup.getDataSource().getProfile())) {
+ retrieveEntitiesByChunk(newConnection.getPrimaryConnection(), exportHistoryGroup, entityHistoryToExport, entityClass);
}
}
- private long countExistingItems(ExportHistoryItemDTO entityHistoryToExport) throws Exception {
+ private long countExistingItems(DataSource dataSource, ExportHistoryItemDTO entityHistoryToExport) throws Exception {
final Class extends EntityBase> entityClass = entityPropertyHolder.getEntityClassFromTableName(entityHistoryToExport.getPublication().getEntityName());
- try (MultiDBTransactionManager newConnection = new MultiDBTransactionManager(entityHistoryToExport.getDataSource().getProfile())) {
+ try (MultiDBTransactionManager newConnection = new MultiDBTransactionManager(dataSource.getProfile())) {
String sql = "SELECT CONVERT(BIGINT, COUNT(*)) FROM " + entityClass.newInstance().getTableName();
return UtilityDB.executeSimpleQueryOnlyFirstRowFirstColumn(newConnection.getPrimaryConnection(), sql);
}
}
- private void retrieveEntitiesByChunk(Connection connection, ExportHistoryItemDTO exportHistoryItem, Class extends EntityBase> entityClass) throws Exception {
+ private void retrieveEntitiesByChunk(Connection connection, ExportHistoryGroupDTO exportHistoryGroup, ExportHistoryItemDTO exportHistoryItem, Class extends EntityBase> entityClass) throws Exception {
- long totalItemCount = exportHistoryItem.getTotalItemCount();
- int chunkSize = 10000;
+ String innerSql = "SELECT * " +
+ "FROM " + exportHistoryItem.getPublication().getEntityName();
+ innerSql = UtilityDB.addwhereCond(innerSql, exportHistoryItem.getPublication().getWhereCond(), true);
- for (int chunkIndex = 0; chunkIndex < (totalItemCount / chunkSize) + 1; chunkIndex++) {
+ UtilityDB.executeSimpleQueryDTOAsync(connection, innerSql, entityClass, data -> {
- while (exportHistoryItem.getToProcessQueue().size() > 30000) {
- Thread.sleep(10 * 1000);
+ exportHistoryGroup.setProcessedItemCount(exportHistoryGroup.getProcessedItemCount() + 1);
+// exportHistoryItem.getToProcessQueue().add(JSON.toJSONString(data));
+
+ try {
+ exportHistoryGroup.getToProcessQueue().add(new Pair<>(exportHistoryItem.getPublication().getEntityName(), jsonObjectMapper.writeValueAsString(data)));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
}
- String innerSql = "SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS row_number " +
- "FROM " + exportHistoryItem.getPublication().getEntityName();
- innerSql = UtilityDB.addwhereCond(innerSql, exportHistoryItem.getPublication().getWhereCond(), true);
-
- String sql = "WITH TempResult AS (\n" +
- innerSql + ")\n" +
- "SELECT TempResult.*\n" +
- "FROM TempResult\n" +
- "ORDER BY row_number\n" +
- "OFFSET (" + chunkIndex + ") * " + chunkSize + " ROWS FETCH NEXT " + chunkSize + " ROWS ONLY";
-
- final List extends EntityBase> selectedChunk = UtilityDB.executeSimpleQueryDTO(connection, sql, entityClass);
-
- if (selectedChunk == null || selectedChunk.isEmpty()) continue;
-
- exportHistoryItem.setProcessedItemCount(exportHistoryItem.getProcessedItemCount() + selectedChunk.size());
- //logger.debug("COUNT: " + exportHistoryItem.getProcessedItemCount());
-
- selectedChunk.forEach(x -> exportHistoryItem.getToProcessQueue().add(x));
- }
+ while ((float) (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / Runtime.getRuntime().totalMemory() > 0.9f) {
+ logger.debug("Memory limit reached: " + (((float) (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / Runtime.getRuntime().totalMemory()) * 100) + "%");
+ try {
+ Thread.sleep(1 * 1000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
}
private void consumeProcessedQueue() {
- final List currentlyInExecutionKeys = new ArrayList<>(currentlyInExecution.keySet());
+ List list = currentlyInExecutionG.get();
+ for (int i = 0; i < list.size(); i++) {
+ ExportHistoryGroupDTO currentGroup = list.get(i);
+ try {
+ internalProcessQueue(currentGroup);
- for (long currentGroupId : currentlyInExecutionKeys) {
- List entitiesToExport = currentlyInExecution.get(currentGroupId);
+ if (currentGroup.isCompletedRead() && currentGroup.getSyncronizedItemCount() >= currentGroup.getTotalItemCount() && currentGroup.getEndTime() == null) {
+ currentGroup.setEndTime(UtilityLocalDate.getNowTime());
+ updateReadyToTransmit(currentGroup);
+ list.remove(i--);
+ }
- for (ExportHistoryItemDTO entityToExport : entitiesToExport) {
- try {
- internalProcessQueue(entityToExport);
- } catch (Exception ex) {
- logger.error(ex.getMessage(), ex);
+ currentGroup.getDataSource().getConnection().commit();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ logger.error(ex.getMessage(), ex);
+ }
+ }
+ }
+
+ private void internalProcessQueue(ExportHistoryGroupDTO currentGroup) throws Exception {
+ String insertSQL = "INSERT INTO " + StbTransactionLog.ENTITY + " (publication_group_id, created_at, user_name, entities, entities_json, group_id)" +
+ " VALUES (?, ?, ?, ?, ?, ?)";
+
+ try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager(currentGroup.getDataSource().getProfile())) {
+
+ while (!currentGroup.getToProcessQueue().isEmpty()) {
+ try (SQLServerPreparedStatement insertBulkPs = (SQLServerPreparedStatement) multiDBTransactionManager.prepareStatement(insertSQL)) {
+ Pair entityJson;
+ while ((entityJson = currentGroup.getToProcessQueue().poll()) != null) {
+ insertBulkPs.setLong(1, currentGroup.getGroupId());
+ insertBulkPs.setObject(2, UtilityLocalDate.getNowTime());
+ insertBulkPs.setString(3, null);
+ insertBulkPs.setString(4, entityJson.getKey());
+ insertBulkPs.setString(5, entityJson.getValue());
+ insertBulkPs.setLong(6, -1);
+
+ insertBulkPs.addBatch();
+ currentGroup.setSyncronizedItemCount(currentGroup.getSyncronizedItemCount() + 1);
+ }
+
+ insertBulkPs.executeLargeBatch();
+
+ System.gc();
}
}
}
}
- private void internalProcessQueue(ExportHistoryItemDTO entityToExport) throws Exception {
- //logger.debug("TBS COUNT: " + entityToExport.getToProcessQueue().size());
- if (entityToExport.getStartDate() == null) entityToExport.setStartDate(UtilityLocalDate.getNowTime());
+ private void updateReadyToTransmit(ExportHistoryGroupDTO exportHistoryGroup) throws Exception {
+ StbPublications stbPublications = new StbPublications()
+ .setId(exportHistoryGroup.getGroupId());
+ stbPublications.setOperation(OperationType.NO_OP);
- try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager(entityToExport.getDataSource().getProfile())) {
+ stbPublications.setStbPublicationsDetails(exportHistoryGroup.getItems().stream()
+ .map(x -> {
+ StbPublicationsDetail stbPublicationsDetail = new StbPublicationsDetail()
+ .setId(x.getPublication().getId())
+ .setReadyToTransmit(true);
- EntityBase entity;
- while ((entity = entityToExport.getToProcessQueue().poll()) != null) {
+ stbPublicationsDetail.setOperation(OperationType.UPDATE);
+ return stbPublicationsDetail;
+ })
+ .collect(Collectors.toList()));
- StbTransactionLog stbTransactionLog = new StbTransactionLog()
- .setPublicationGroupId(entityToExport.getPublicationGroupId())
- .setCreatedAt(UtilityLocalDate.getNowTime())
- .setEntitiesJson(jsonObjectMapper.writeValueAsString(entity))
- .setGroupId(-1)
- .setEntities(entityToExport.getPublication().getEntityName());
-
- stbTransactionLog
- .setOperation(OperationType.INSERT);
-
- stbTransactionLog.manageWithParentConnection(multiDBTransactionManager.getPrimaryConnection());
- entityToExport.setSyncronizedItemCount(entityToExport.getSyncronizedItemCount() + 1);
- }
-
-
- }
+ stbPublications.manageWithParentConnection(exportHistoryGroup.getDataSource().getConnection());
}
-
public List getStatus() {
-
List statusList = new ArrayList<>();
- HashMap> total = new HashMap<>();
+ for (ExportHistoryGroupDTO currentGroup : currentlyInExecutionG.get()) {
- for (Long key : currentlyInExecution.keySet()) {
-
- final LocalDateTime startDate = currentlyInExecution.get(key).stream()
- .map(ExportHistoryItemDTO::getStartDate)
- .filter(Objects::nonNull)
- .min(Comparator.naturalOrder())
- .orElse(null);
+ final LocalDateTime startDate = currentGroup.getStartTime();
long totalCount = 0;
long processedCount = 0;
long itemsPerSec = 1;
- LocalDateTime estimatedEnd = null;
+ LocalDateTime estimatedEnd = currentGroup.getEndTime();
if (startDate != null) {
- totalCount = currentlyInExecution.get(key).stream()
- .map(ExportHistoryItemDTO::getTotalItemCount)
- .reduce(0L, Long::sum);
+ totalCount = currentGroup.getTotalItemCount();
+ processedCount = currentGroup.getSyncronizedItemCount();
- processedCount = currentlyInExecution.get(key).stream()
- .map(ExportHistoryItemDTO::getSyncronizedItemCount)
- .reduce(0L, Long::sum);
-
- final long secondsBetween = ChronoUnit.SECONDS.between(startDate, UtilityLocalDate.getNowTime());
+ final long secondsBetween = ChronoUnit.SECONDS.between(startDate, estimatedEnd != null ? estimatedEnd : UtilityLocalDate.getNowTime());
itemsPerSec = processedCount / (secondsBetween == 0 ? 1 : secondsBetween);
- //if(itemsPerSec == 0) itemsPerSec = 1 / 60;
double secsToEnd = (double) totalCount / (itemsPerSec == 0 ? 1 : itemsPerSec);
-
estimatedEnd = startDate.plusSeconds((long) secsToEnd);
}
+
statusList.add(new ExportHistoryStatusDTO()
- .setPublicationGroupId(key)
+ .setPublicationGroupId(currentGroup.getGroupId())
.setStartedAt(startDate)
.setTotalCount(totalCount)
.setProcessedCount(processedCount)
diff --git a/ems-core/src/main/java/it/integry/ems/sync/AsyncManager.java b/ems-core/src/main/java/it/integry/ems/sync/AsyncManager.java
index bc1b99cc40..7b967bcc4f 100644
--- a/ems-core/src/main/java/it/integry/ems/sync/AsyncManager.java
+++ b/ems-core/src/main/java/it/integry/ems/sync/AsyncManager.java
@@ -1,18 +1,21 @@
package it.integry.ems.sync;
+import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement;
import it.integry.annotations.PostContextConstruct;
-import it.integry.common.var.CommonConstants;
import it.integry.ems.json.JSONObjectMapper;
import it.integry.ems.looper.service.LooperService;
import it.integry.ems.settings.Model.AvailableConnectionsModel;
import it.integry.ems.settings.Model.SettingsModel;
import it.integry.ems.settings.SettingsController;
import it.integry.ems.sync.MultiDBTransaction.MultiDBTransactionManager;
-import it.integry.ems.utility.UtilityDebug;
import it.integry.ems_model.base.EntityBase;
import it.integry.ems_model.entity.StbPublicationsDetail;
+import it.integry.ems_model.entity.StbTransactionLog;
+import it.integry.ems_model.types.OperationType;
import it.integry.ems_model.utility.UtilityDB;
+import it.integry.ems_model.utility.UtilityLocalDate;
import it.integry.ems_model.utility.UtilityString;
+import javafx.util.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.josql.Query;
@@ -21,11 +24,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ContextLoader;
-import java.io.StringWriter;
import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;
@Component
@@ -45,12 +49,14 @@ public class AsyncManager {
private final static HashMap> cachedSetup = new HashMap<>();
+ private final static ConcurrentLinkedQueue> toBeSavedQueue = new ConcurrentLinkedQueue<>();
@PostContextConstruct
public void init() {
- if (!UtilityDebug.isDebugExecution() && !UtilityDebug.isIntegryServer()) {
- looperService.add(this::internalCachePublicationsSetup, 5 * 60 * 1000, AsyncManager.class.getName());
- }
+ //if (!UtilityDebug.isDebugExecution() && !UtilityDebug.isIntegryServer()) {
+ looperService.add(this::internalCachePublicationsSetup, 5 * 60 * 1000, "sync-setup-cache");
+ looperService.add(this::consumeToBeSavedQueue, 20 * 1000, "sync-flush-data");
+ //}
}
private void internalCachePublicationsSetup() {
@@ -130,49 +136,91 @@ public class AsyncManager {
}
- public static void saveNewTransaction(Connection connection, EntityBase entityBase, int transactionGroupId) throws Exception {
-
- String transactionDate = new SimpleDateFormat(CommonConstants.DATETIME_FORMAT_YMD).format(new Date());
- int transactionId = 0;
-
- Integer tmpTransactionId = UtilityDB.executeSimpleQueryOnlyFirstRowFirstColumn(
- connection, "SELECT max(transaction_id) as max_id from stb_transaction_log_db");
-
- if (tmpTransactionId != null) transactionId = tmpTransactionId;
- transactionId++; //Incremento l'ID
+ public static Long saveNewTransaction(Connection connection, String dbName, EntityBase entityBase, long publicationId, Long transactionGroupId) throws Exception {
+ //TODO: Calc transaction group ID here
+ if (transactionGroupId == null) transactionGroupId = getNextTransactionGroupId(connection, dbName);
JSONObjectMapper jsonObjectMapper = ContextLoader.getCurrentWebApplicationContext().getBean(JSONObjectMapper.class);
- StringWriter writer = new StringWriter();
- jsonObjectMapper.writeValue(writer, entityBase);
-
- String entityName = entityBase.getTableName().toUpperCase();
-
- String sql =
- "INSERT INTO stb_transaction_log_db(transaction_id, transaction_group_id, transaction_date, user_name, transaction_json, entity_name_list) " +
- "VALUES (" + transactionId + "," + transactionGroupId + ",'" + transactionDate + "', null, '%s', " + UtilityDB.valueToString(entityName) + ")";
-
- String jsonString = writer.toString().replace("'", "''");
-
- sql = String.format(sql, jsonString);
-
- PreparedStatement psExec = connection.prepareStatement(sql);
- psExec.executeUpdate();
- psExec.close();
-
- }
-
-
- public static int getNextTransactionGroupId(Connection connection) throws Exception {
- int transactionGroupId = 0;
-
- Integer tmpTransactionGroupId = UtilityDB.executeSimpleQueryOnlyFirstRowFirstColumn(
- connection, "SELECT MAX(transaction_group_id) AS max_id from stb_transaction_log_db");
-
- if (tmpTransactionGroupId != null) transactionGroupId = tmpTransactionGroupId;
- transactionGroupId++; //Incremento l'ID
+ StbTransactionLog stbTransactionLog = new StbTransactionLog()
+ .setCreatedAt(UtilityLocalDate.getNowTime())
+ .setEntities(entityBase.getTableName().toUpperCase())
+ .setEntitiesJson(jsonObjectMapper.writeValueAsString(entityBase))
+ .setPublicationGroupId(publicationId)
+ .setUserName(entityBase.getUsername())
+ .setGroupId(transactionGroupId);
+ stbTransactionLog.setOperation(OperationType.INSERT);
+ toBeSavedQueue.add(new Pair<>(dbName, stbTransactionLog));
return transactionGroupId;
}
+
+ public static long getNextTransactionGroupId(Connection connection, String dbName) throws Exception {
+
+ final long maxToBeProcessed = toBeSavedQueue.stream().filter(x -> x.getKey().equalsIgnoreCase(dbName))
+ .map(x -> x.getValue().getGroupId())
+ .max(Long::compare)
+ .orElse(0L);
+
+ long transactionGroupId = 0;
+
+ if (maxToBeProcessed <= 0) {
+ Long tmpTransactionGroupId = UtilityDB.executeSimpleQueryOnlyFirstRowFirstColumn(
+ connection, "SELECT MAX(group_id) AS max_id FROM " + StbTransactionLog.ENTITY);
+
+ tmpTransactionGroupId = tmpTransactionGroupId != 0 ? tmpTransactionGroupId : 0L;
+
+ transactionGroupId = Math.max(maxToBeProcessed, tmpTransactionGroupId);
+ } else {
+ transactionGroupId = maxToBeProcessed;
+ }
+
+ transactionGroupId++; //Incremento l'ID
+ return transactionGroupId;
+ }
+
+
+ private void consumeToBeSavedQueue() {
+ if(cachedSetup.entrySet().stream().anyMatch(x -> x.getValue() != null && x.getValue().stream().anyMatch(y -> !y.isReadyToTransmit())))
+ return;
+
+ List dbNamesToConnect = toBeSavedQueue.stream().map(Pair::getKey).distinct().collect(Collectors.toList());
+
+ final List databaseConnections = settingsModel.getAvailableConnections().stream()
+ .filter(x -> dbNamesToConnect.stream().anyMatch(y -> x.getDbName().equalsIgnoreCase(y)))
+ .collect(Collectors.toList());
+
+ String insertSQL = "INSERT INTO " + StbTransactionLog.ENTITY + " (publication_group_id, created_at, user_name, entities, entities_json, group_id)" +
+ " VALUES (?, ?, ?, ?, ?, ?)";
+
+ Pair itemToSave = null;
+ while ((itemToSave = toBeSavedQueue.poll()) != null) {
+ final Pair finalItemToSave = itemToSave;
+ final StbTransactionLog stbTransactionLog = finalItemToSave.getValue();
+
+ AvailableConnectionsModel connectionModel = databaseConnections.stream()
+ .filter(x -> x.getDbName().equalsIgnoreCase(finalItemToSave.getKey()))
+ .findFirst()
+ .get();
+
+ try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager(connectionModel);
+ SQLServerPreparedStatement insertBulkPs = (SQLServerPreparedStatement) multiDBTransactionManager.prepareStatement(insertSQL)) {
+
+ insertBulkPs.setLong(1, stbTransactionLog.getGroupId());
+ insertBulkPs.setObject(2, stbTransactionLog.getCreatedAt());
+ insertBulkPs.setString(3, stbTransactionLog.getUserName());
+ insertBulkPs.setString(4, stbTransactionLog.getEntities());
+ insertBulkPs.setString(5, stbTransactionLog.getEntitiesJson());
+ insertBulkPs.setLong(6, stbTransactionLog.getGroupId());
+
+
+ insertBulkPs.executeLargeUpdate();
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
}
diff --git a/ems-core/src/main/java/it/integry/ems/sync/MultiDBTransaction/MultiDBTransactionManager.java b/ems-core/src/main/java/it/integry/ems/sync/MultiDBTransaction/MultiDBTransactionManager.java
index 403b90c5a5..04c32f7574 100644
--- a/ems-core/src/main/java/it/integry/ems/sync/MultiDBTransaction/MultiDBTransactionManager.java
+++ b/ems-core/src/main/java/it/integry/ems/sync/MultiDBTransaction/MultiDBTransactionManager.java
@@ -46,6 +46,10 @@ public class MultiDBTransactionManager implements AutoCloseable{
public MultiDBTransactionManager() {
}
+ public MultiDBTransactionManager(AvailableConnectionsModel connectionsModel) throws Exception {
+ this(connectionsModel.getProfileName(), true);
+ }
+
public MultiDBTransactionManager(String profileDb) throws Exception {
this(profileDb, true);
}
diff --git a/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryGroupDTO.java b/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryGroupDTO.java
index 17f50742f5..201f1aaa63 100644
--- a/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryGroupDTO.java
+++ b/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryGroupDTO.java
@@ -1,11 +1,27 @@
package it.integry.ems.sync.dto;
+import it.integry.ems.datasource.DataSource;
+import javafx.util.Pair;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
public class ExportHistoryGroupDTO {
+ private DataSource dataSource;
private long groupId;
- private List items;
+ private LocalDateTime startTime;
+ private LocalDateTime endTime;
+ private boolean completedRead;
+ private long totalItemCount;
+ private long processedItemCount;
+ private long syncronizedItemCount;
+ private List items = new ArrayList<>();
+
+ private final Queue> toProcessQueue = new ConcurrentLinkedQueue<>();
public long getGroupId() {
@@ -25,4 +41,72 @@ public class ExportHistoryGroupDTO {
this.items = items;
return this;
}
+
+
+ public Queue> getToProcessQueue() {
+ return toProcessQueue;
+ }
+
+ public LocalDateTime getStartTime() {
+ return startTime;
+ }
+
+ public ExportHistoryGroupDTO setStartTime(LocalDateTime startTime) {
+ this.startTime = startTime;
+ return this;
+ }
+
+ public DataSource getDataSource() {
+ return dataSource;
+ }
+
+ public ExportHistoryGroupDTO setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ return this;
+ }
+
+ public long getTotalItemCount() {
+ return totalItemCount;
+ }
+
+ public ExportHistoryGroupDTO setTotalItemCount(long totalItemCount) {
+ this.totalItemCount = totalItemCount;
+ return this;
+ }
+
+ public long getProcessedItemCount() {
+ return processedItemCount;
+ }
+
+ public ExportHistoryGroupDTO setProcessedItemCount(long processedItemCount) {
+ this.processedItemCount = processedItemCount;
+ return this;
+ }
+
+ public long getSyncronizedItemCount() {
+ return syncronizedItemCount;
+ }
+
+ public ExportHistoryGroupDTO setSyncronizedItemCount(long syncronizedItemCount) {
+ this.syncronizedItemCount = syncronizedItemCount;
+ return this;
+ }
+
+ public boolean isCompletedRead() {
+ return completedRead;
+ }
+
+ public ExportHistoryGroupDTO setCompletedRead(boolean completedRead) {
+ this.completedRead = completedRead;
+ return this;
+ }
+
+ public LocalDateTime getEndTime() {
+ return endTime;
+ }
+
+ public ExportHistoryGroupDTO setEndTime(LocalDateTime endTime) {
+ this.endTime = endTime;
+ return this;
+ }
}
diff --git a/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryItemDTO.java b/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryItemDTO.java
index 4dac862e21..6addf4e26e 100644
--- a/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryItemDTO.java
+++ b/ems-core/src/main/java/it/integry/ems/sync/dto/ExportHistoryItemDTO.java
@@ -1,41 +1,12 @@
package it.integry.ems.sync.dto;
-import it.integry.ems.datasource.DataSource;
-import it.integry.ems_model.base.EntityBase;
-
import java.time.LocalDateTime;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
public class ExportHistoryItemDTO {
- private long publicationGroupId;
- private DataSource dataSource;
private PublicationDTO publication;
private LocalDateTime startDate;
- private long totalItemCount;
- private long processedItemCount;
- private long syncronizedItemCount;
- private Queue toProcessQueue = new ConcurrentLinkedQueue();
-
- public long getPublicationGroupId() {
- return publicationGroupId;
- }
-
- public ExportHistoryItemDTO setPublicationGroupId(long publicationGroupId) {
- this.publicationGroupId = publicationGroupId;
- return this;
- }
-
- public DataSource getDataSource() {
- return dataSource;
- }
-
- public ExportHistoryItemDTO setDataSource(DataSource dataSource) {
- this.dataSource = dataSource;
- return this;
- }
public PublicationDTO getPublication() {
return publication;
@@ -54,40 +25,4 @@ public class ExportHistoryItemDTO {
this.startDate = startDate;
return this;
}
-
- public long getTotalItemCount() {
- return totalItemCount;
- }
-
- public ExportHistoryItemDTO setTotalItemCount(long totalItemCount) {
- this.totalItemCount = totalItemCount;
- return this;
- }
-
- public long getProcessedItemCount() {
- return processedItemCount;
- }
-
- public ExportHistoryItemDTO setProcessedItemCount(long processedItemCount) {
- this.processedItemCount = processedItemCount;
- return this;
- }
-
- public Queue getToProcessQueue() {
- return toProcessQueue;
- }
-
- public ExportHistoryItemDTO setToProcessQueue(Queue toProcessQueue) {
- this.toProcessQueue = toProcessQueue;
- return this;
- }
-
- public long getSyncronizedItemCount() {
- return syncronizedItemCount;
- }
-
- public ExportHistoryItemDTO setSyncronizedItemCount(long syncronizedItemCount) {
- this.syncronizedItemCount = syncronizedItemCount;
- return this;
- }
}
diff --git a/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationService.java b/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationService.java
index f70e3c4b06..0dd4d88f8e 100644
--- a/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationService.java
+++ b/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationService.java
@@ -5,11 +5,10 @@ import it.integry.ems.sync.AsyncHistoryManager;
import it.integry.ems.sync.MultiDBTransaction.MultiDBTransactionManager;
import it.integry.ems.sync.dto.ExportHistoryStatusDTO;
import it.integry.ems.sync.dto.PublicationDTO;
-import it.integry.ems.utility.UtilityEntity;
-import it.integry.ems_model.base.EntityBase;
import it.integry.ems_model.base.EntityPropertyHolder;
import it.integry.ems_model.entity.StbPublicationsDetail;
import it.integry.ems_model.utility.Query;
+import it.integry.ems_model.utility.UtilityDB;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -37,11 +36,12 @@ public class RemoteSynchronizationService {
private EntityProcessor entityProcessor;
public void startPublication(long groupId) throws Exception {
- StbPublicationsDetail tmpStbPublicationsDetail = new StbPublicationsDetail();
- String whereCond = Query.format("stb_publication_id = %s AND export_history = %s", groupId, 1);
+ String sql = Query.format("SELECT * FROM " + StbPublicationsDetail.ENTITY + " WHERE stb_publication_id = %s AND export_history = %s AND ready_to_transmit = 0", groupId, 1);
- final List extends EntityBase> select = tmpStbPublicationsDetail.select(multiDBTransactionManager.getPrimaryConnection(), whereCond);
- final List stbPublicationsDetails = UtilityEntity.toCustomEntity(select);
+ final List stbPublicationsDetails = UtilityDB.executeSimpleQueryDTO(multiDBTransactionManager.getPrimaryConnection(), sql, StbPublicationsDetail.class);
+
+ if(stbPublicationsDetails == null)
+ throw new Exception("Non è stata trovata alcuna pubblicazione da poter avviare (ID: " + groupId + ")");
for (StbPublicationsDetail stbPublicationsDetail : stbPublicationsDetails) {
asyncHistoryManager.addToExportQueue(multiDBTransactionManager.getPrimaryDatasource(),
diff --git a/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationSetupService.java b/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationSetupService.java
index 964cf90204..ec22387650 100644
--- a/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationSetupService.java
+++ b/ems-core/src/main/java/it/integry/ems/sync/service/RemoteSynchronizationSetupService.java
@@ -79,7 +79,7 @@ public class RemoteSynchronizationSetupService {
.collect(toList());
publicationGroupDTO.setPublications(publications);
- boolean atLeastOneActiveToExport = publications.stream().anyMatch(publicationDTO -> publicationDTO.getExportHistory() && publicationDTO.getActive());
+ boolean atLeastOneActiveToExport = publications.stream().anyMatch(publicationDTO -> publicationDTO.getExportHistory() && publicationDTO.getActive() && !publicationDTO.getReadyToTransmit());
boolean alreadyExporting = currentExportStatus.stream().anyMatch(x -> x.getPublicationGroupId() == publicationGroupDTO.getId());
publicationGroupDTO.setCanStartExport(atLeastOneActiveToExport && !alreadyExporting);
@@ -113,7 +113,7 @@ public class RemoteSynchronizationSetupService {
.setActive(publicationToInsert.getActive())
.setWhereCondField(publicationToInsert.getWhereCond())
.setExportHistory(publicationToInsert.getExportHistory())
- .setReadyToTransmit(!publicationToInsert.getReadyToTransmit());
+ .setReadyToTransmit(!publicationToInsert.getExportHistory());
stbPublicationsDetail.setOperation(OperationType.INSERT);
StbPublications stbPublications = new StbPublications()
@@ -190,7 +190,7 @@ public class RemoteSynchronizationSetupService {
stbPublicationsDetail = entityProcessor.processEntity(stbPublicationsDetail, multiDBTransactionManager);
- if(publicationDTO.getExportHistory() != null)
+ if(publicationDTO.getExportHistory() != null && !stbPublicationsDetail.isReadyToTransmit())
stbPublicationsDetail.setExportHistory(publicationDTO.getExportHistory());
if(publicationDTO.getActive() != null)
diff --git a/ems-core/src/main/java/it/integry/ems_model/base/EntityBase.java b/ems-core/src/main/java/it/integry/ems_model/base/EntityBase.java
index b5cea009c9..7f7df79f56 100644
--- a/ems-core/src/main/java/it/integry/ems_model/base/EntityBase.java
+++ b/ems-core/src/main/java/it/integry/ems_model/base/EntityBase.java
@@ -113,7 +113,7 @@ public abstract class EntityBase implements Serializable, Cloneable, EntityInter
//ID del gruppo di transazioni per le Sync OFFLINE
@JsonIgnore
- private Integer transactionGroupId = null;
+ private Long transactionGroupId = null;
@JsonIgnore
private int queryTimeoutSeconds = 60 * 30;
@@ -927,8 +927,7 @@ public abstract class EntityBase implements Serializable, Cloneable, EntityInter
long publicationId = AsyncManager.getPublicationIdIfExists(dbName, this);
if (publicationId > 0) {
- if (transactionGroupId == null) transactionGroupId = AsyncManager.getNextTransactionGroupId(connection);
- AsyncManager.saveNewTransaction(connection, this, transactionGroupId);
+ transactionGroupId = AsyncManager.saveNewTransaction(connection, dbName, this, publicationId, transactionGroupId);
}
}
}
@@ -1988,11 +1987,11 @@ public abstract class EntityBase implements Serializable, Cloneable, EntityInter
return builder.toString();
}
- public Integer getTransactionGroupId() {
+ public Long getTransactionGroupId() {
return transactionGroupId;
}
- public void setTransactionGroupId(Integer transactionGroupId) {
+ public void setTransactionGroupId(Long transactionGroupId) {
this.transactionGroupId = transactionGroupId;
}
@@ -2005,8 +2004,7 @@ public abstract class EntityBase implements Serializable, Cloneable, EntityInter
try {
field.setAccessible(true);
idRiga = (Integer) field.get(entityBase);
- } catch (Exception e) {
-
+ } catch (Exception ignored) {
}
return idRiga;
}
diff --git a/ems-core/src/main/java/it/integry/ems_model/base/EntityInterface.java b/ems-core/src/main/java/it/integry/ems_model/base/EntityInterface.java
index 5672afc87e..904735468f 100644
--- a/ems-core/src/main/java/it/integry/ems_model/base/EntityInterface.java
+++ b/ems-core/src/main/java/it/integry/ems_model/base/EntityInterface.java
@@ -83,9 +83,9 @@ public interface EntityInterface {
EntityException getException();
- Integer getTransactionGroupId();
+ Long getTransactionGroupId();
- void setTransactionGroupId(Integer transactionGroupId);
+ void setTransactionGroupId(Long transactionGroupId);
void resetTransactionGroupId();
diff --git a/ems-core/src/main/java/it/integry/ems_model/db/AsyncResultSetMapper.java b/ems-core/src/main/java/it/integry/ems_model/db/AsyncResultSetMapper.java
new file mode 100644
index 0000000000..3f9ad304c4
--- /dev/null
+++ b/ems-core/src/main/java/it/integry/ems_model/db/AsyncResultSetMapper.java
@@ -0,0 +1,282 @@
+package it.integry.ems_model.db;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.microsoft.sqlserver.jdbc.SQLServerResultSet;
+import it.integry.ems.expansion.RunnableArgs;
+import it.integry.ems.expansion.RunnableArgsWithReturn;
+import it.integry.ems.utility.UtilityDebug;
+import it.integry.ems_model.ImportExport.Interfaces.IExportFormat;
+import it.integry.ems_model.ImportExport.Interfaces.IImportFormat;
+import it.integry.ems_model.annotation.Clob;
+import it.integry.ems_model.annotation.MapToTable;
+import it.integry.ems_model.annotation.SqlField;
+import it.integry.ems_model.base.EntityBase;
+import it.integry.ems_model.exception.DataConverterNotFoundException;
+import it.integry.ems_model.resolver.SqlFieldHolder;
+import it.integry.ems_model.types.OperationType;
+import it.integry.ems_model.utility.UtilityDB;
+import it.integry.ems_model.utility.UtilityString;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import javax.validation.constraints.NotNull;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.*;
+
+public class AsyncResultSetMapper {
+
+
+ private final Logger logger = LogManager.getLogger();
+
+
+ @NotNull
+ public static List> mapResultSetToHashMap(ResultSet rs) throws SQLException {
+ ResultSetMetaData md = rs.getMetaData();
+ int columns = md.getColumnCount();
+ List> list = new ArrayList>();
+ while (rs.next()) {
+ HashMap row = new HashMap(columns);
+ for (int i = 1; i <= columns; ++i) {
+ row.put(md.getColumnName(i), rs.getObject(i));
+ }
+ list.add(row);
+ }
+ return list;
+ }
+
+ public static Map.Entry> mapResultSetToArray(ResultSet rs) throws SQLException {
+ ResultSetMetaData md = rs.getMetaData();
+ int columns = md.getColumnCount();
+
+ String[] columnNames = new String[columns];
+ for (int i = 1; i <= columns; ++i) {
+ columnNames[i - 1] = md.getColumnName(i).toLowerCase();
+ }
+
+ List