Получите запрос, который будет выполнен, используя Спецификации JPA весной - PullRequest
1 голос
/ 18 июня 2019

У меня есть весенний проект, в котором мне нужно экспортировать набор результатов запроса в таблицу 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 секунд), а подготовка таблицы Excel с использованием библиотек POI также занимает почти 60 секунд.

Когда я попытался экспортировать CSV-файл вместо использования результирующего набора (вместо Java-POJO), он заканчивался менее чем за 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);

Есть ли способ достичь чего-то подобного?

1 Ответ

1 голос
/ 25 июня 2019

Это немного сложно, потому что вы можете получить нестандартный запрос, подобный этому:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...