Как стать автором
Обновить

Комментарии 37

При наличии парсера запроса немного странным выглядит необходимость указания его типа (type = QT_SELECT). Его можно из запроса извлечь.


А также, не пробовали получить названия параметров методов, чтобы явно не писать в аннотации TargetFilter имена? Вроде это можно.

>Его можно из запроса извлечь

В общем случае — нельзя. Хранимая процедура может возвращать результат как select, а может и нет. Узнать вы это можете — но только при выполнении.

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

Не, ну в принципе в метаданных процедуры скорее всего есть все что нужно, я это просто к тому, что это а) это не слишком просто, б) не является частью стандарта SQL-92, и в) все это можно узнать только у базы, путем выполнения запроса. То есть просто парсер тут ничего не даст, по внешнему виду вызова процедуры ничего не видно.
А также, не пробовали получить названия параметров методов, чтобы явно не писать в аннотации TargetFilter имена

В семерке, не знаю как в 8-9, есть такой аттрибут (речь про формат .class) MethodParameters в котором есть часть, отвечающая за имя параметра:
MethodParameters_attribute {
       u2 attribute_name_index;
       u4 attribute_length;
       u1 parameters_count;
       {   u2 name_index;
           u2 access_flags;
       } parameters[parameters_count];
   }

name_index — это индекс указывает на значение в ConstantPool, где храниться имя параметра, но в описании этого элемента имеем:
The value of the name_index item must either be zero or a valid index into
the constant_pool table.
На своем опыте скажу, что частенько встречал 0, вместо реально-ожидаемых значений. Поэтому, отвечая на Ваш 2ой вопрос, скажу НЕТ. Если же имеется альтернативный способ извлечения, подскажите, буду Вам признателен.

посмотрите как это делает Spring Data — они же тоже имена у Param из имён переменных могут брать

Просто Netbeans в некоторых случаях показывает нормальные имена у параметров, даже если исходного кода или документации к джарнику не предоставляется, следовательно, эта информация где-то в class-файле. С другой стороны, это он делает не всегда, значит, она необязательная.


Если вы по аннотациям генерируете код во время компиляции, то сделать точно можно. А если рефлексией балуетесь, то вот не всегда, выходит, можно будет.

Согласен и подумаю как справить. Сейчас это проблема связанна с тем, что выбор стратегии работы с типом SQL-запроса начинается задолго до непосредственного разбора самого запроса. промахнулся
>ограничить поддерживаемый набор SQL конструкций

А вы уверены, что не потеряете при этом всю расширенную функциональность конкретной реализации?
А вы уверены, что не потеряете при этом всю расширенную функциональность конкретной реализации?


Да нет конечно. Вы только гляньте на примерный обзор возможных конструкций в том или ином диалекте. Здесь и десятка людей не хватит, чтобы их все поддерживать. Здесь возможен на мой взгляд только компромисс и точечный выбор специфичных, но ЧАСТО используемых вещей, вроде постраничной разбивки, определенных форматов тип данных (даты, время). Возможно что-то еще. Но в целом, если придерживаться стандарта SQL-92, то думаю можно поддерживать оговоренную функциональность
Увы, в стандарт например не входит такая вещь, как merge. И при этом она еще и делается сильно по-разному у MS SQL и PostgreSQL, так, для примера.
очень похоже на mybatis. и кстати, т.н. «динамические фильтры» идут там из коробки.
Когда готовил статью, я погружался в парадигму того или иного существующего фреймворка, где-то, чтобы просто освежить память, с чем-то просто никогда не работал. Мне кажется, то, что Вы называете динамическими фильтрами в MyBatis суть Dynamic SQL и кодить там все же придется, но в xml. Из достоинств Dynamic SQL — достаточно неплохой язык выражений и допускает его быстрое расширение, если потребуется. Но ключевое слово здесь кодить. С похожестью, наверное я не соглашусь, он просто другой.
Мне кажется, то, что Вы называете динамическими фильтрами в MyBatis суть Dynamic SQL и кодить там все же придется, но в xml

Не понимаю, что в вашем представлении значит «кодить». Написание SQL к кодингу не относится?
Есть ещё один известный мне способ делать запросы с динамической подстановкой параметров — Sql Provider:
@InsertProvider(type=ContactMapperSqlProvider.class, method=ContactMapperSqlProvider.CREATE_CONTACT_QUERY_NAME)
Long createContact(Contact contact);
...
class ContactMapperSqlProvider{
        private static final String CREATE_CONTACT_QUERY_NAME = "createContact";

        public String createContact(Contact contact){
            return new SQL() {{
                INSERT_INTO("TUTORS");
                VALUES("name", "#{name}").VALUES("surname", "#{surname}").VALUES("patronymic", "#{patronymic}").VALUES("description", "#{description}")
                    .VALUES("user_id", "#{user.id}");
                if (contact.getBirthDate() != null)
                    VALUES("birthday", "#{birthday}");
            }}.toString();
        }
    }

Чем то похоже на Criteria API в JPA/Hibernate, но выглядит симпатичнее
Да в том то и дело
     if (contact.getBirthDate() != null) VALUES("birthday", "#{birthday}");
Под этим я и понимаю кодинг — именно наличие оператора if.
Разумеется, указывать сам параметр и его значение в том или ином виде при любом подходе придется, другое дело для того же батиса, кто им мешал сделать так:
     // как вариант N1
     VALUES("birthday", "#{birthday}?");
     // или так как другой вариант N2
     VALUES("birthday", "#{birthday or nothing}");
или еще, как-то, более декларативно, согласно их представлениям понятия краткости и лаконичности.
Самое главное, я ни в коем случае не пытаюсь приуменьшить значение батиса для эко системы java, не подумайте или какого-либо другого фреймворка. Более того, я даже очень рад, что нам с Вами есть что сравнивать и из чего выбирать
Как мне кажется, в данном случае явное лучше неявного, и вариант с if-ом будет более поддерживаемым.
Согласен, конструкция с if нагляднее. Краткость != удобство.

ORM-фреймворки, ORM-объекты, SQL-фреймворки, XML, ещё какая-то херь — ради формирования текста sql- запроса? Да на кой это нужно?

это все не для формирвания sql запроса а скорее для удобногго и корректного маппинга в объекты.
Лично я не против такой позиции. Но если высказали А, то нужно сказать и Б.
A — есть у Вас подготовленный String sql-запрос к БД на выборку данных.
Б — а что дальше?
А дальше у нас всё просто — создаём соединение, создаём Recordset, выполняем запрос, итоги запроса обрабатываем так, как того требует текущая задача, закрываем соединение, и во избежание утечек памяти присваиваем использованным для выгрузки объектам значение Nothing.
А у Вас как?
А дальше у нас всё просто — создаём соединение, создаём Recordset, выполняем запрос, итоги запроса обрабатываем так, как того требует текущая задача, закрываем соединение, и во избежание утечек памяти присваиваем использованным для выгрузки объектам значение Nothing.
А у Вас как?
Пишешь sql-запрос, скармливаешь его движку, вуа ля и получаешь то, что нужно. Разумеется, соединение достаешь из пула, отработал таск, кладешь обратно.
В мире .net как-то с этим проще… например https://github.com/linq2db/linq2db или https://github.com/StackExchange/Dapper/blob/master/Readme.md
Чем проще?
Скажите, а чем Вам таки не угодил JDBI? Вы указали, что рассматривали его, а в Вашем решении предлагаете нечто до боли напоминающее его Sql Objects: https://jdbi.github.io/#_sql_objects

Собственно, мы активно используем в продакшене именно его, и большинство методов DAO действительно выглядят как методы без реализации с аннотациями, внутри которых описаны sql-запросы.
Про угодил, не угодил я ничего в разрезе JDBI не писал. Его подход, а точнее стиль программирования очень похож c рассматриваемым решением. Он отлично покроет такие операции как INSERT, UPDATE и DELETE. Но больше всего в проектах приходится возиться с операцией SELECT. И здесь прослеживается основная разница: JDBI пошел по пути SpringTemplate — RowMapper, ColumnMapper и все такое. RefOrms пошел по пути анализа SQL-запроса, для того, чтобы мепить, фильтровать и прочие.
Автору спасибо за статью, но должен обратить внимание на орфографические ошибки — «преступить», «походу», «Да в прочим» и т.п. И разные переводы одного понятия — «меппинг — мэппинг».
А собственно я так и не понял, автор сам пишет такую библиотеку или показывает какую-то готовую?
сам
Для своего использования или в публику тоже выйдет?
Исходники открыты на гитхабе, есть артефакт в мавен централ репозитории, не вижу каких-либо противопоказаний для использования желающими :) Другое дело, что его пилить нужно, батчинг, хранимые процедуры, генерация id для insert и так по-мелочи. Присоединяйтесь, коли будет желание, пару пул реквестов я уже заапрувил.
Вы забыли пласт фреймворков на базе EAV, который в сумме по объему рынка существенно обходит ORM.
Entity Attribute Value — аналог ORM, как и ORM является абстракцией над SQL.
Однако по своей механике довольно сильно отличается. Конечно же имеет как плюсы, так и минусы относительно ORM. Минусы относительно SQL у них схожи.
EAV есть основа платформ типа WP & Drupal. Которые сильно отличаются от MVC/ORM фреймворков, но при этом имеют примерно те же возможности, где то даже больше.
Сюда принимаем еще 2 факта:
— Грань между сайтом и веб приложением сегодня стерта
— Вслед за этим некогда простые CMS сумели эволюционировать в полноценные веб фреймворки

Однако они оставили за собой право лидеров рынка. Существенно обгоняя ORM подобные фреймворки как по доле рынка, так и по гибкости.

Я не против ORM, даже за в некоторых задачах. Также как за SQL в тех задачах где это уместно. Однако чаще всего я предпочитаю работать с EAV. Как и большинство участников мирового рынка если принимать во внимание доли реального использования и занимаемого объема рынка.

И тот факт что вы не учли сей тип фреймворков работы с данными — говорит о пробелах в данном материале.
Возможно стоит это восполнить.
Пробелы есть, скрывать не буду. Никогда не сталкивался в проде с таким решением.

Простите, из какого фреймворка из вышеперечисленных это: @TargetFilter?
И хотелось бы конечно сравнения, какие из них поддерживают эту и другие фичи..

@TargetFilter из RefOrms
Указание имени параметра фильтра в аннотации поддерживает JDBI, называется правда там это аннотация Bind.
Сравнение фреймворков это дело хорошее, но боюсь выходит за рамки этой статьи
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации