Доброго времени суток, уважаемый читатель! Осень, холодно за окном. Следующая тема не имеет ничего общего с вышеназванными вещами, однако может быть полезна заблудившимся путникам по просторам монструозной платформы force.com. Не будем тянуть резину - сразу к делу!
Задача: Получить в запросе SOQL значения по всем полям.
Безголовыпринятоерешение: [SELECT поле1, поле2...полеN fromТаблица];
Решение: А теперь давайте трезво рассуждать. Пускай у нас имеется, таблица с 10-ю полями. И чтобы сделать выборку, мы включим в наш запрос эти 10 полей. Хорошо, а к примеру, если мы пошли пить кофе, которое переросло в долгоиграющий обед, а в это самое время ваш лучший друг и товарищ-программист добавит еще одно кастомное поле в объект... и соберет, ко всему, еще на продакшен change set, то ваш ждет приятный сюрприз в виде ошибки. Кто виноват? Что делать? Ответим на второй философский вопрос - использовать Schema.
Итак, пишем свою крохотную утилитку для самых маленьких. Для начала выносим наши константы.
Задача: Получить в запросе SOQL значения по всем полям.
Безголовыпринятоерешение: [SELECT поле1, поле2...полеN fromТаблица];
Решение: А теперь давайте трезво рассуждать. Пускай у нас имеется, таблица с 10-ю полями. И чтобы сделать выборку, мы включим в наш запрос эти 10 полей. Хорошо, а к примеру, если мы пошли пить кофе, которое переросло в долгоиграющий обед, а в это самое время ваш лучший друг и товарищ-программист добавит еще одно кастомное поле в объект... и соберет, ко всему, еще на продакшен change set, то ваш ждет приятный сюрприз в виде ошибки. Кто виноват? Что делать? Ответим на второй философский вопрос - использовать Schema.
Итак, пишем свою крохотную утилитку для самых маленьких. Для начала выносим наши константы.
- public with sharing class SOQLUtil {
- private final static String SELECT_SOQL = 'SELECT ';
- private final static String FROM_SOQL = ' FROM ';
- private final static String COMMA_SOQL = ',';
- private final static String WHERE_SOQL = ' WHERE ';
- private final static String LIMIT_SOQL = ' LIMIT ';
- ...
- }
Тут все просто. Я включил в свой код еще и пару дополнительный штучек WHERE и LIMIT. Но оних чуть позже. Далее, вторым степом создаем наши переменные, которые будут вращаться в круговороте нашей задумки.
- private String theQuery {get; set;}
- private String objectName {get; set;}
- private String whereField{get; set;}
- private String whereValue{get; set;}
- private String limitScore{get; set;}
Поясним, что theQuery - это строка нашего SOQL-запроса. objectName - уникальное имя нашего объекта. Остальные поля являются необязательными, они лишь созданы для демонстрации нечто большего, чем простая выборка данных.
Далее прошу убрать от мониторов слабонервных и тех, кто боится обилия кода. Остальных, прошу сильно не вдаваться в код. Привожу работу метода полностью. Пояснение ниже.
Далее прошу убрать от мониторов слабонервных и тех, кто боится обилия кода. Остальных, прошу сильно не вдаваться в код. Привожу работу метода полностью. Пояснение ниже.
- public void getSelectAllShow(){
- // START SOQL SELECT
- this.theQuery = SELECT_SOQL;
- Map<String, Schema.SObjectType> globaldesMap = Schema.getGlobalDescribe();
- Schema.DescribeSObjectResult describeSObj = globaldesMap.get(this.objectName).getDescribe();
- if(describeSObj != null){
- Map<String, Schema.SObjectField> fieldMap = describeSObj.fields.getMap();
- List<Schema.SObjectField> fldObjMapValues = fieldMap.values();
- // SELECT FIELDS
- this.selectFieldsForQuery(fldObjMapValues);
- // FROM
- theQuery += FROM_SOQL + this.objectName;
- // IS WHERE
- if(!String.isEmpty(this.whereField) && !String.isEmpty(this.whereValue)){
- for(Schema.SObjectField s : fldObjMapValues){
- if(s.getDescribe().getName().equals(this.whereField)){
- this.theQuery += WHERE_SOQL + this.whereField + '=' + '\'' + whereValue +'\'';
- }
- }
- }
- //IS LIMIT
- if(!String.isEmpty(this.limitScore)){
- final Boolean isValidNumberic = this.validNumber();
- if(isValidNumberic){
- theQuery += LIMIT_SOQL + this.limitScore;
- }
- }
- System.debug('SF Query: ' + theQuery);
- sObject[] sobjects = Database.query(theQuery);
- if(sobjects.size() < 1000){
- System.debug('SObject ' + sobjects);
- }
- }
- }
globaldesMap - хранит нашу мапу объектов. describeSObj - хранит результат одного нашего объекта. Заметьте, чтобы получить наш результат по объекту, мы просто даем мапе на вход его имя this.objectName. И после долгих преобразований мы достукиваемся до филдов нашего объекта. ( fldObjMapValues).
Расписываем наш List филдов в методе this.selectFieldsForQuery(fldObjMapValues);
Расписываем наш List филдов в методе this.selectFieldsForQuery(fldObjMapValues);
- private void selectFieldsForQuery(List<Schema.SObjectField> fldObjMapValues){
- for(Schema.SObjectField s : fldObjMapValues){
- String theName = s.getDescribe().getName();
- theQuery += theName + COMMA_SOQL;
- }
- // Trim last comma
- theQuery = theQuery.subString(0, theQuery.length() - 1);
- }
Я думаю без лишних комментариев. Просто прогоняем наш лист и извлекаем оттуда все имена филдов, которые тут же записываем в нашу строку SOQL- запроса. Далее обращаем внимание на наши ограничения. Они так же сделаны по принципу "разделяй и властвуй". Если у нас есть еще LIMIT, то для валидности числа в строке finalBoolean isValidNumberic = this.validNumber(); Расписываем в методе:
- private Boolean validNumber() {
- if (String.isEmpty(limitScore) || limitScore == null) {
- limitScore = '';
- }
- String limitRegex = '-?\d+(\.\d+)?';
- Matcher nMatcher = Pattern.compile(limitRegex).matcher(limitScore);
- return (!nMatcher.matches()) ? false : true;
- }
Cообственно, говоря, вот и все... Бояться больше нечего. Непосредственно весь код утилиты.
- public with sharing class SOQLUtil {
- private final static String SELECT_SOQL = 'SELECT ';
- private final static String FROM_SOQL = ' FROM ';
- private final static String COMMA_SOQL = ',';
- private final static String WHERE_SOQL = ' WHERE ';
- private final static String LIMIT_SOQL = ' LIMIT ';
- private String theQuery {get; set;}
- private String objectName {get; set;}
- private String whereField{get; set;}
- private String whereValue{get; set;}
- private String limitScore{get; set;}
- private void selectFieldsForQuery(List<Schema.SObjectField> fldObjMapValues){
- for(Schema.SObjectField s : fldObjMapValues){
- String theName = s.getDescribe().getName();
- theQuery += theName + COMMA_SOQL;
- }
- // Trim last comma
- theQuery = theQuery.subString(0, theQuery.length() - 1);
- }
- private Boolean validNumber() {
- if (String.isEmpty(limitScore) || limitScore == null) {
- limitScore = '';
- }
- String limitRegex = '-?\d+(\.\d+)?';
- Matcher nMatcher = Pattern.compile(limitRegex).matcher(limitScore);
- return (!nMatcher.matches()) ? false : true;
- }
- public void getSelectAllShow(){
- // START SOQL SELECT
- this.theQuery = SELECT_SOQL;
- Map<String, Schema.SObjectType> globaldesMap = Schema.getGlobalDescribe();
- Schema.DescribeSObjectResult describeSObj = globaldesMap.get(this.objectName).getDescribe();
- if(describeSObj != null){
- Map<String, Schema.SObjectField> fieldMap = describeSObj.fields.getMap();
- List<Schema.SObjectField> fldObjMapValues = fieldMap.values();
- // SELECT FIELDS
- this.selectFieldsForQuery(fldObjMapValues);
- // FROM
- theQuery += FROM_SOQL + this.objectName;
- // IS WHERE
- if(!String.isEmpty(this.whereField) && !String.isEmpty(this.whereValue)){
- for(Schema.SObjectField s : fldObjMapValues){
- if(s.getDescribe().getName().equals(this.whereField)){
- this.theQuery += WHERE_SOQL + this.whereField + '=' + '\'' + whereValue +'\'';
- }
- }
- }
- //IS LIMIT
- if(!String.isEmpty(this.limitScore)){
- final Boolean isValidNumberic = this.validNumber();
- if(isValidNumberic){
- theQuery += LIMIT_SOQL + this.limitScore;
- }
- }
- System.debug('SF Query: ' + theQuery);
- try {
- sObject[] sobjects = Database.query(theQuery);
- if(sobjects.size() < 1000){
- System.debug('SObject ' + sobjects);
- }
- } catch(DmlException e) {
- System.debug('DML Exception in' + theQuery);
- }
- }
- }
- @IsTest
- public static void theTestUtil() {
- final String testSObject = 'Code_Review__c';
- final String testWhereField = 'Name_Rev__c';
- final String testWhereValue = 'Test';
- final String testLimitScore = '1';
- SOQLUtil testObj = new SOQLUtil();
- testObj.objectName = testSObject;
- testObj.whereField = testWhereField;
- testObj.whereValue = testWhereValue;
- testObj.limitScore = testLimitScore;
- testObj.getSelectAllShow();
- }
- }