среда, 28 марта 2012 г.

Search & delete thumbs.db commands for Windows

Search all hidden Thumbs.db in current folder and its subfolders:
dir Thumbs.db /s /ah
Recursively delete all Thumbs.db in current folder:
del / S / AR / AS / AA / AA Thumbs.db

вторник, 10 января 2012 г.

JDBC > ResultSet > getDate - форматирование даты в Java

Задача: используя чистый JDBC, выбрать из базы данных поле с типом DATE и форматировать дату к нужному формату.

Решение: для получения даты из набора данных ResultSet необходимо воспользоваться методом getDate(), результат работы которого отформатировать при помощи родного java класса java.text.SimpleDateFormat. Как это всё выглядит в сборке показано ниже - код отлично документирован.

import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class getDateFormat {
  public static void main(String[] args){
    // создаем подключение, в данном примере к Oracle
    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
    Connection conn = DriverManager
             .getConnection("jdbc:oracle:thin:@192.168.0.1:1521:db11g",
                            "user_name", "user_pass"
                      );
    // выполняем запрос, возвращающий в составе полей
    // d_point типа DATE
    ResultSet rs = conn.createStatement()
           .executeQuery("select id, action, d_point from users_log");
    // перебираем результаты в цикле
    while (rs.next()){
      // выводим id записи и текстовое поле action
      System.out.println("Id: ".concat( rs.getInt("id").toString() )
                         .concat("\n")
                         .concat("Action: ").concat(
                           rs.getString("action")
                         )
      );
      // получаем поле с датой
      Date d_point = rs.getDate("d_point");
      // форматируем дату и выводим
      String dateFormatted = new SimpleDateFormat("dd.MM.yyyy")
                                      .format( d_point ).toString();
      System.out.println("Date: ".concat(dateFormatted));
    }
  }
}

Параметры форматирования для SimpleDateFormat приведены в официальной документации.

вторник, 8 ноября 2011 г.

Массивы в PL/SQL

PL/SQL, являясь процедурным расширением языка структурированных запросов SQL, имеет все необходимые составляющие для полнофункционального программирования логики. Ветвления, циклы, массивы и т.д. - все как у людей:) Работа с массивами в PL/SQL, однако, отличается от стандартного для многих распространенных языков программирования подхода.

С массивами, как известно, можно делать три вещи: объявлять массив, добавлять/изменять/читать данные по индексу и обходить массив в цикле. Эти действия мы и рассмотрим.

среда, 14 сентября 2011 г.

Использование Ext JS 4 виджетов в рамках Ext JS 3 интерфейса

Ext JS 4 представляет разработчикам много новых возможностей, в числе которых, например, большое количество новых графиков и диаграмм. Сравните - для четвертой версии приведено 22 примера использования элементов Chart против всего четырех примеров для третьей версии. Внушающе, не правда ли?

Однако что, если в наличии есть большое приложение, реализованное на третьей версии Ext JS и возникает необходимость использования некоторых виджетов четвертой версии? Например, типична ситуация, когда в приложение нужно добавить новые диаграммы, но переписывать всё на "четверку" нецелесообразно.

среда, 31 августа 2011 г.

Справочники и классификаторы

Редкая крупная база данных и программная система на её основе сегодня обходится без использования справочников и классификаторов. Ситуация с применением этих терминов очень интересна благодаря тому, что по существу определения им никто толком дать не может. Кто-то говорит, что справочник - особый тип классификатора, кто-то - что классификатор это подтип справочника. Так что же это такое и в чем разница?

Как ни странно, ответ на этот вопрос следует искать в названиях терминов. Классификатор - классифицирует, справочник - хранит справочные данные. Фактически, это полностью описывает  оба термина. Классификаторы разрабатываются для группировки объектов по некоторым критериям с целью последующей удобной работы с этими группами и в группах, часто бывают иерархическими. Пример классификатора - ОКЭР (Общероссийский классификатор экономических регионов России), который содержит в себе информацию о регионах, разбитую по группам, в качестве критерия классификации выступают различные экономические показатели.

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

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

понедельник, 29 августа 2011 г.

Oracle Database: получить поля таблицы и комментарии к ним


Проектная документации на разработку программных систем, имеющих в основе базу данных, подразумевает наличие описания структур БД. Как правило, в техническом проекте приводится схема БД, получаемая обратной разработкой (reverse engineering) готовых таблиц, и информация об атрибутах таблиц. Для составления схем можно использовать бесплатный SQL Developer Data Modeler (как пользоваться), для описания атрибутов таблиц же удобно составить следующий SQL запрос:

SELECT col.table_name,
  col.column_name,
  col.data_type,
  col.data_length,
  col.data_precision,
  col.data_scale,
  col.nullable,
  com.comments
FROM ALL_TAB_COLUMNS col
LEFT JOIN user_col_comments com
ON (col.table_name  = com.table_name
AND col.column_name = com.column_name)
WHERE col.TABLE_NAME = 'PUO_FAIP'
ORDER BY table_name,
  column_name;

Как видим, запрос возвращает поля таблицы PUO_FAIP (column_name), тип данных в поле (data_type), длину данных для текстовых типов (data_length), точность и масштаб для числовых типов (data_precision и data_scale соответственно), возможность поля хранить значение NULL (nullable) и, наконец, комментарий (comments). Полученные данные легко экспортировать в текстовый редактор для оформления документации.

PS. При создании таблиц рекомендуется сразу создавать и комментарии к ее полям, это просто:
-- комментарий к полю
COMMENT ON COLUMN SCHEMA_NAME.TABLE_NAME.COLUMN_NAME IS
   'Текстовый комментарий к полю таблицы';

-- комментарий к таблице
COMMENT ON TABLE SCHEMA_NAME.TABLE_NAME IS
   'Текстовый комментарий к таблице';

понедельник, 15 августа 2011 г.

ExtJS: разработка интерфейса независимо от источников данных. Кросс-доменный AJAX для загрузки хранилищ

Удаленные источники для хранилищ ExtJS - это источники, расположенные в другом домене или, как их еще называют, кросс-доменные источники. Вероятно, вы знаете о том, что традиционные XMLHttpRequest запросы (известные в народе как AJAX запросы) имеют ряд ограничений, связанных в первую очередь с безопасностью - в частности, XMLHttpRequest запросы могут быть посланы только к адресу с одноименным протоколом, доменом и портом по отношению к запрашивающей странице. Таким образом, нельзя сделать традиционный AJAX запрос с сайта site1.com к сайту site2.com.

Тем не менее, такая необходимость часто возникает, в таких случаях используется так называемый cross-domain  (кросс-доменный) AJAX. Стоит отметить, что непосредственно к AJAX эти технологии уже не относятся, название в данном случае - не более, чем дань традиции. О методах, используемых в кросс-доменных запросах, можно почитать, например, в статье на javascript.ru.

Одной из проблем разработки интерфейсов на ExtJS является зависимость от динамически загружаемых данных: фактически, большинство компонентов фреймворка используют те или иные данные, получаемые при помощи AJAX запросов. Например, так выглядит традиционное описание хранилища:

myStore = new Ext.data.JsonStore({
    url:    'getUsers',
    method: 'POST',
    root: 'items',
    fields: [{name:"id"},{name:"name"}]
});

URL, указанный первым параметром, ссылается на страницу того же домена, в котором должна находиться разрабатываемая страница, иначе AJAX запрос на загрузку данных не сможет быть произведен. Таким образом, разрабатываемая html страница и javascript код в ее составе должны быть частью домена-источника данных. Это не всегда удобно и не всегда возможно.

Использование кросс-доменных запросов в таких случаях - отличное решение. Посмотрите, как просто можно заставить работать ExtJS приложение с данными любого домена:

myStore = new Ext.data.JsonStore({
    proxy: new Ext.data.ScriptTagProxy({
            url:    'http://vasilij.com/getUsers',
    }),
    method: 'POST',
    root: 'items',
    fields: [{name:"id"},{name:"name"}]
});

В код сервлета необходимо добавить отслеживание GET параметра callback. Дело в том, что при использовании ScriptTagProxy, ExtJS добавляет в строку запроса параметр callback, таким образом, что в нашем случае запрос будет иметь вид:

http://vasilij.com/getUsers&callback=stcCallback10

Возвращаемый JSON должен быть обернут в функцию, название которой соответствует переданному параметру callback. В случае сервлета:

String callback = request.getParameter("callback");
if (callback == null){
  response.setContentType("text/javascript");
  out.println(jsonString);
}
else{
  response.setContentType("application/x-json");
  out.println(callback.concat("(").concat(jsonString).concat(")"));
}

Таким образом, при отсутствии callback параметра в строке запроса возвращается обычный JSON, в противном случае JSON оборачивается в функцию.

После внесения в код приложения описанных изменений можно разрабатывать интерфейс абсолютно независимо от всей остальной части приложения; сервлеты-поставщики данных могут находиться в любом домене, и даже простая html страница на рабочем столе с подключенным ExtJS сможет получать данные и корректно их обрабатывать и отображать. После окончания процесса разработки и тестирования можно заменить Ext.data.ScriptTagProxy на Ext.data.HttpProxy для использования AJAX запросов.

Приятного кодинга вам!