QueryDSL использует слишком много памяти.Альтернатива для лучшего подхода к памяти - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть веб-API Spring Boot, который использует querydsl для извлечения результатов из реляционной БД, в моем случае это MariaDB.

Вот Служба:

@Override
public List fetchProductAuditTrailResult(TxnRequestDTO<HeaderDTO, ProductAuditTrailReportRequestDTO> request)
        throws ParseException {
    List<LIHistoryProductEntity> txnResponse = new ArrayList<LIHistoryProductEntity>();
    logger.info("Entered ReportService.fetchProductAuditTrailResult()");
    QLIHistoryProductEntity qLiHistoryProductEntity = QLIHistoryProductEntity.lIHistoryProductEntity;
    Map<String, StringPath> notNullInputMap = getFieldMappingForProductAuditReport(request);
    logger.info("Received non empty map for input fields");
    txnResponse = jpaQueryFactory.selectFrom(qLiHistoryProductEntity)
            .where(buildExpressionForProductAuditReport(notNullInputMap, qLiHistoryProductEntity, request)).fetch();

    for (LIHistoryProductEntity entry : txnResponse) {
        entry.setPlanType(properties.getPlanType().get(entry.getPlanType()));
        entry.setMaintenanceStatus(properties.getMaintenaceStatus().get(entry.getMaintenanceStatus()));
    }

    logger.info("EXITING ReportService.fetchProductAuditTrailResult()");
    return txnResponse;
}

private Predicate buildExpressionForProductAuditReport(Map<String, StringPath> notNullInputMap,
        QLIHistoryProductEntity entity, TxnRequestDTO<HeaderDTO, ProductAuditTrailReportRequestDTO> request)
        throws ParseException {

    BooleanExpression expression = null;
    Map<String, StringPath> fieldMapping = getFieldMappingForProductAuditReport(request);

    ProductAuditTrailReportRequestDTO searchDTO = request.getTxnRequest();

    for (Map.Entry<String, String> entry : searchDTO.entrySet()) {
        String fieldName = entry.getKey();
        String fieldValue = entry.getValue();
        if (!StringUtils.isEmpty(fieldValue) && fieldMapping.containsKey(fieldName)) {
            expression = (expression != null) ? expression.and(fieldMapping.get(fieldName).eq(fieldValue))
                    : fieldMapping.get(fieldName).eq(fieldValue);
        }
    }

    QLIHistoryProductEntity qLIProductEntity = QLIHistoryProductEntity.lIHistoryProductEntity;
    if (searchDTO.containsKey(RECEIVED_DATE_FROM) && !searchDTO.get(RECEIVED_DATE_FROM).isEmpty()
            && !searchDTO.get(RECEIVED_DATE_TO).isEmpty() && searchDTO.containsKey(RECEIVED_DATE_TO)) {
        BooleanExpression dateBetween = qLIProductEntity.recordTimestamp.between(
                formatter.parse(searchDTO.get(RECEIVED_DATE_FROM)),
                formatter.parse(searchDTO.get(RECEIVED_DATE_TO)));
        expression = (expression != null) ? expression.and(dateBetween) : dateBetween;
    }

    return expression;

}


private Map<String, StringPath> getFieldMappingForProductAuditReport(
        TxnRequestDTO<HeaderDTO, ProductAuditTrailReportRequestDTO> request) {

    QLIHistoryProductEntity qLIProductEntity = QLIHistoryProductEntity.lIHistoryProductEntity;
    Map<String, StringPath> fieldMapping = new HashMap<>();
    fieldMapping.put("productCode", qLIProductEntity.productCode);
    fieldMapping.put("insurerComponentCode", qLIProductEntity.componentCode);
    fieldMapping.put("insurerName", qLIProductEntity.insurerName);
    fieldMapping.put("productName", qLIProductEntity.productName);

    return fieldMapping;
}

Вот сущность:

@Entity
@Table(name = "DBS_LI_PRODUCT_HISTORY")
public class LIHistoryProductEntity extends LIProductEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@Column(name = "PRODUCT_CODE")
private String productCode;

@Column(name = "COMPONENT_CODE")
private String componentCode;

//getters and setters

Сопоставленный суперкласс:

@MappedSuperclass
public class LIProductEntity {

@Column(name = "RECORD_STATUS")
private String recordStatus;

@Column(name = "PLAN_TYPE")
private String planType;

@Column(name = "MAINTENANCE_INDICATOR")
private String maintenanceStatus;

@Column(name = "PRODUCT_NAME")
private String productName;

@Column(name = "INSURER_NAME")
private String insurerName;

@Column(name = "RECORD_TIMESTAMP")
private Date recordTimestamp;

@Column(name = "INSURER_CODE")
private String insurerCode;

@Column(name = "COUNTRY_CODE")
private String insurerCountryCode;

@Column(name = "GROUP_POLICY_INDICATOR")
private String groupPolicyIndicator;

@Column(name = "GROUP_POLICY_NO")
private String groupPolicyNo;

@Column(name = "PRODUCT_TENURE")
private String productTenure;

@Column(name = "LAUNCH_START_DATE")
private Date launchStartDate;

@Column(name = "LAUNCH_END_DATE")
private Date launchEndDate;



@Column(name = "MAIN_CURRENCY_TYPE")
private String mainCurrencyType;

@Column(name = "IBMB_TEMPLATE_NAME")
private String ibmbTemplateName;

@Column(name = "IBMB_TEMPLATE_ID")
private String ibmbTemplateId;

@Column(name = "CUSTOMER_SEGMENT_MM")
private Character customerSegmentMM;

@Column(name = "CUSTOMER_SEGMENT_TR")
private Character customerSegmentTR;

@Column(name = "CUSTOMER_SEGMENT_TPC")
private Character customerSegmentTPC;

@Column(name = "CUSTOMER_SEGMENT_PB")
private Character customerSegmentPB;

@Column(name = "POLICY_CATEGORY")
private String policyCategory;

@Column(name = "COVERAGE_TYPE")
private String coverageType;

@Column(name = "PRODUCT_GROUPING")
private String productCategory;

@Column(name = "REMARKS")
private String remarks;

@Column(name = "LAST_UPDATED_BY")
private String lastUpdatedBy;

@Column(name = "LAST_UPDATED_DATE_TIME")
private Date lastUpdatedDateTime;


@Column(name = "APPROVED_BY")
private String approvedBy;

@Column(name = "APPROVED_DATE_TIME")
private Date lastApprovedDate;

@Column(name = "BANK_ACCOUNT_NO")
private String bankAccountNo;

//getters and setters

Проблема здесьв том, что когда querydsl занимает память, он не отпускает ее, и это вызывает проблемы.Нам уже пришлось масштабировать наше приложение с 1 ГБ памяти до 2 ГБ памяти, и даже этого недостаточно.

Мой вариант использования:

Тело запроса будет иметь поисковые фильтры, которые могут иметь или не иметь значения, и мы должны получать результаты из БД на основе этих значений.

Пожалуйста, помогите предложить лучшую альтернативу, которая освободит память при простое процессора.

Я думал о переходе на JPQL, но не знаю, как написать запрос, поскольку возможны различные комбинации, поскольку все поля поиска могут иметь или не иметь значения.

Или желательно использовать старый добрый JDBC?

Помощь и предложения приветствуются.

...