繁体   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