簡體   English   中英

在 Spring 中使用 JPA 規范獲取要執行的查詢

[英]Get the query to be executed using JPA Specifications in Spring

我有一個 spring 項目,我需要將查詢結果集導出到 Excel 表中。 目前我正在使用JPA repository從數據庫中獲取數據,並且我正在使用Apache POI庫從這些數據中准備 excel 表。

// Get data from DB using jpaRepository
Page<MyPOJO> data = myPOJOJpaRepository.findAll(specifications, pageRequest);

// Prepare Excel Sheet from the data object using POI libraries

現在,問題是獲取 Java POJO 形式的數據花費了太多時間(將近 60 秒),並且使用 POI 庫准備 excel 表也花費了近 60 秒。

當我嘗試使用結果集(而不是 java POJO)導出 csv 文件時,它在 10 秒內完成。

 ResultSet resultSet = statement.executeQuery("select * from table where some_filters");
 File file = writeResultsToCSVFile(resultSet);

我正在使用JPA specifications在當前架構中構建查詢。 無論如何要獲取將要執行的查詢,以便我可以直接獲取結果集(而不是 POJO)並准備 csv 文件。

// I'm looking for something like follows:
ResultSet resultSet = statement.executeQuery(specifications.getQuery());
File file = writeResultsToCSVFile(resultSet);

有沒有辦法實現這樣的目標?

這有點棘手,因為您可以獲得這樣的非標准查詢:

select generatedAlias0 from Pets as generatedAlias0 where generatedAlias0.pet_name=:param0

您必須獲得查詢,然后您需要操作諸如請求字段和綁定參數之類的東西(管理它們的類型。請注意,在此示例中我只管理了字符串類型)。

因此,假設您正在使用 Hibernate,您可以執行以下操作:

/**
 *
 */
public static Specification<Pets> findByCriteria() {

    return new Specification<Pets>() {

        @Override
        public Predicate toPredicate(Root<Pets> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

            List<Predicate> predicates = new ArrayList<Predicate>();

            // solo attivita attive
            predicates.add(cb.equal(root.get("pet_name"), "Chelsea"));

            return cb.and(predicates.toArray(new Predicate[]{}));
        }
    };
}

/**
 * TODO MANAGE VARIOUS TYPES
 */
private String createParam(Parameter<?> p, Query<?> q) {

    Class<?> clz = p.getParameterType();
    if (clz == String.class) {
        return "'" + q.getParameterValue(p.getName()) + "'";
    }
    return "";
}


/**
 *
 */
public void getEnterprisesAdmin() {

    Specification<Pets> spec = this.findByCriteria();

    CriteriaBuilder builder = this.em.getCriteriaBuilder();
    CriteriaQuery<Pets> query = builder.createQuery(Pets.class);

    Root<Pets> root = query.from(Pets.class);

    Predicate predicate = spec.toPredicate(root, query, builder);
    query.where(predicate);

    TypedQuery<Pets> findAllBooks = em.createQuery(query);
    Query<Pets> q = findAllBooks.unwrap(Query.class);

    String strQuery = q.getQueryString();

    strQuery = Pattern.compile("(.*?)select \\w*").matcher(strQuery).replaceFirst("SELECT *");

    Set<Parameter<?>> pList = q.getParameters();
    Iterator<Parameter<?>> iter = pList.iterator();
    for (int i=0; i<pList.size(); i++) {
        Parameter<?> p = iter.next();
        strQuery = strQuery.replace(":" + p.getName(), this.createParam(p, q));
    }

    try {
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mempoi?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", "root", "");
        Statement stmt = conn.createStatement();
        ResultSet resultSet = stmt.executeQuery(strQuery);

        resultSet.next();
        System.out.println("PET NAME: " + resultSet.getString("pet_name"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

您給了我一個好主意,讓我在我的庫MemPOI (設計用於管理像您這樣的案例)中實現下一個功能,該功能為 Apache POI 提供抽象層。 我將直接從Specification實現導出

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM