AliasToBeanResultTransformer и Hibernate SQLQuery - PullRequest
3 голосов
/ 14 декабря 2010

У меня довольно сложный запрос (слишком много вложенных уровней для запросов HQL или Criteria), поэтому я написал его как SQLQuery.Мне бы очень хотелось использовать AliasToBeanResultTransformer для преобразования моих результатов в список, но у меня возникли некоторые проблемы.Я включил фрагменты кода ниже того, что у меня есть прямо сейчас.

Когда я записываю результаты для преобразованного запроса, я вижу, что преобразователь создает Список, однако все поля в каждом AdvancedClauseSearchResultDTO равны нулю.Я предполагаю, что это означает, что я делаю что-то не так с псевдонимами ... что AliasToBeanResultTransformer не может найти правильные установщики для вызова.Тем не менее, класс AdvancedClauseSearchResultDTO имеет открытые сеттеры для каждого из столбцов, которые я добавил в строку sql.Если бы это был запрос Criteria, я бы использовал проекции, чтобы определить псевдоним для каждого возвращаемого столбца, но я не уверен, как выполнить то же самое с помощью SQLQuery.

Любые советы о том, какполучить псевдонимы, чтобы ResultTransformer мог их использовать?Я видел ограниченную документацию, в которой говорилось, что использование метода «as aliasName» должно работать, но, похоже, это не для меня.

Начальный фрагмент определения строки запроса, обратите внимание на 'as 'определения псевдонима

StringBuffer clauseBaseQuery = new StringBuffer();
        clauseBaseQuery.append("select ");
        clauseBaseQuery.append(" clauseDetail.clause_detail_id as clauseDetailId,");
        clauseBaseQuery.append(" clauseDetail.clause_id as clauseId,");
        clauseBaseQuery.append(" providers.provider_name as provider, ");
        clauseBaseQuery.append(" products.product_name as product, ");

SQLQuery создание и настройка resultTransformer

Query query  = session.createSQLQuery(clauseBaseQuery.toString());
query.setResultTransformer(new AdvancedClauseSearchResultTransformer());
return (List<AdvancedClauseSearchResultDTO>)query.list();

AdvancedClauseSearchResultTransformer (использует AliasToBeanResultTransformer и затем выполняет некоторые дополнительныеобработка):

class AdvancedClauseSearchResultTransformer implements ResultTransformer {

        //Use the aliasTransformer to do most of the work
        ResultTransformer aliasTransformer = Transformers.aliasToBean(AdvancedClauseSearchResultDTO.class);

        @Override
        public List transformList(List list) {
            log.debug("transforming CLAUSE results");
            List<AdvancedClauseSearchResultDTO> result = aliasTransformer.transformList(list);
            //for each row, set the status field
           for (AdvancedClauseSearchResultDTO dto : result) {
                log.debug("dto = " + dto);
                String status = null;
                Date effectiveDate = dto.getEffectiveDate();
                Date terminationDate = dto.getTerminationDate();
                Date now = new Date(System.currentTimeMillis());
                if (now.before(effectiveDate)) {
                    status = "Pending";
                } else if (now.after(terminationDate)) {
                    status = "Terminated";
                } else {
                    status = "Active";
                }
                dto.setStatus(status);

                if (StringUtils.isNotEmpty(dto.getReasonForAmendment())){
                    dto.setAmended(Boolean.TRUE);
                }else{
                    dto.setAmended(Boolean.FALSE);
                }
            }

            return result;
        }

        @Override
        public Object transformTuple(Object[] os, String[] strings) {
            Object result = aliasTransformer.transformTuple(os, strings);

            return result;
        }
    }

Ответы [ 3 ]

14 голосов
/ 30 мая 2011

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

Различные бэкэнды БД используют регистронезависимое именование для столбцов , если только не экранирует их должным образом, поэтому они заканчиваются получением как CLAUSEDETAILID или clausedetailid, даже если вы указали имя результата столбца с соответствующим случай.

В PostgreSQL (и я верю, что и в Oracle) вы должны написать свой запрос следующим образом (обратите внимание на цитирование в столбце):

StringBuffer clauseBaseQuery = new StringBuffer();
clauseBaseQuery.append("select ");
clauseBaseQuery.append(" clauseDetail.clause_detail_id as \"clauseDetailId\",");
clauseBaseQuery.append(" clauseDetail.clause_id as \"clauseId\",");
clauseBaseQuery.append(" providers.provider_name as \"provider\", ");
clauseBaseQuery.append(" products.product_name as \"product\", ");
Query query  = session.createSQLQuery(clauseBaseQuery.toString());

Это позволит Hibernate правильно распознать свойство и отобразить результат в bean-компонент, при условии, что вы также указали преобразование:

query.setResultTransformer(Transformers.aliasToBean(AdvancedClauseSearchResultDTO.class));

как было предложено @ zinan.yumak.

4 голосов
/ 15 декабря 2010

Сегодня я провел еще несколько исследований по этому вопросу и, наконец, заметил хороший след в стеке об основной ошибке, которую я получил, и запись в спящем форуме, которая помогла мне преодолеть это.

Исключение, которое я получалis: Причина: org.hibernate.PropertyNotFoundException: Не удалось найти установщик для CLAUSEDETAILID

Похоже, что Hibernate принимает мои псевдонимы в случае верблюда и превращает их во все прописные буквы, поэтому он не может найти соответствующие установщикив моем классе AdvancedClauseSearchResultDTO.

Вот запись на форуме, которая указала мне правильное направление:

https://forum.hibernate.org/viewtopic.php?f=1&t=1001608

В итоге я использовал подход, подробно описанный в этом посте, для моегособственный ResultTransformer, и это работает для меня.

3 голосов
/ 14 декабря 2010

Я думаю, что это не очень хороший способ написать преобразователь результата для решения вашей проблемы.Попробуйте что-то вроде этого,

Query query  = session.createSQLQuery(clauseBaseQuery.toString());
query.setResultTransformer(Transformers.aliasToBean(AdvancedClauseSearchResultDTO.class));

И в классе AdvancedClauseSearchResultDTO измените методы установки для установки необходимых полей.Например,

class AdvancedClauseSearchResultDTO { 
    private Date effectiveDate;

    private String status;
    .
    .

    public void getEffectiveDate() {
        return effectiveDate;
    }

    public void setEffectiveDate(Date aDate) {
                Date now = new Date(System.currentTimeMillis());
                if (now.before(effectiveDate)) {
                    this.status = "Pending";
                } else if (now.after(terminationDate)) {
                    this.status = "Terminated";
                } else {
                    this.status = "Active";
                }
        this.effectiveDate = aDate;
    }
}

У вас есть идея ...

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