Реформа SQL-ориентированного подхода в DAO
Комментарии (10)
12 июня 2017 в 16:53 (комментарий был изменён)
+1↑
↓
При наличии парсера запроса немного странным выглядит необходимость указания его типа (
type = QT_SELECT
). Его можно из запроса извлечь.А также, не пробовали получить названия параметров методов, чтобы явно не писать в аннотации
TargetFilter
имена? Вроде это можно.12 июня 2017 в 17:17
0↑
↓
>Его можно из запроса извлечьВ общем случае — нельзя. Хранимая процедура может возвращать результат как select, а может и нет. Узнать вы это можете —, но только при выполнении.
12 июня 2017 в 17:42
0↑
↓
А также, не пробовали получить названия параметров методов, чтобы явно не писать в аннотации 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ой вопрос, скажу НЕТ. Если же имеется альтернативный способ извлечения, подскажите, буду Вам признателен.
12 июня 2017 в 16:58 (комментарий был изменён)
+1↑
↓
Согласен и подумаю как справить. Сейчас это проблема связанна с тем, что выбор стратегии работы с типом SQL-запроса начинается задолго до непосредственного разбора самого запроса. промахнулся12 июня 2017 в 17:16
+1↑
↓
>ограничить поддерживаемый набор SQL конструкцийА вы уверены, что не потеряете при этом всю расширенную функциональность конкретной реализации?
12 июня 2017 в 17:28
0↑
↓
А вы уверены, что не потеряете при этом всю расширенную функциональность конкретной реализации?
Да нет конечно. Вы только гляньте на примерный обзор возможных конструкций в том или ином диалекте. Здесь и десятка людей не хватит, чтобы их все поддерживать. Здесь возможен на мой взгляд только компромисс и точечный выбор специфичных, но ЧАСТО используемых вещей, вроде постраничной разбивки, определенных форматов тип данных (даты, время). Возможно что-то еще. Но в целом, если придерживаться стандарта SQL-92, то думаю можно поддерживать оговоренную функциональность
12 июня 2017 в 17:49
+1↑
↓
очень похоже на mybatis. и кстати, т.н. «динамические фильтры» идут там из коробки.12 июня 2017 в 18:10
0↑
↓
Когда готовил статью, я погружался в парадигму того или иного существующего фреймворка, где-то, чтобы просто освежить память, с чем-то просто никогда не работал. Мне кажется, то, что Вы называете динамическими фильтрами в MyBatis суть Dynamic SQL и кодить там все же придется, но в xml. Из достоинств Dynamic SQL — достаточно неплохой язык выражений и допускает его быстрое расширение, если потребуется. Но ключевое слово здесь кодить. С похожестью, наверное я не соглашусь, он просто другой.12 июня 2017 в 19:25
0↑
↓
Мне кажется, то, что Вы называете динамическими фильтрами в 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, но выглядит симпатичнее12 июня 2017 в 19:36
0↑
↓
Да в том то и дело
Под этим я и понимаю кодинг — именно наличие оператора if.if (contact.getBirthDate() != null) VALUES("birthday", "#{birthday}");
Разумеется, указывать сам параметр и его значение в том или ином виде при любом подходе придется, другое дело для того же батиса, кто им мешал сделать так:
или еще, как-то, более декларативно, согласно их представлениям понятия краткости и лаконичности.// как вариант N1 VALUES("birthday", "#{birthday}?"); // или так как другой вариант N2 VALUES("birthday", "#{birthday or nothing}");
Самое главное, я ни в коем случае не пытаюсь приуменьшить значение батиса для эко системы java, не подумайте или какого-либо другого фреймворка. Более того, я даже очень рад, что нам с Вами есть что сравнивать и из чего выбирать