Rambler's Top100IT • archiv

rus / eng | Логин | Комментарий к колонке | Печать | Почта | Клуб




Колонки


Разработка мобильного словаря с использованием JDBC. Часть 5

 
(Николай Зайкин)

5. Создание графического клиентского JDBC приложения.

Писать аналогичное приложение (как для доступа к CGI скриптам через web) с нуля не совсем разумно, так как это достаточно большая задача. Ей был посвящен целый курс статей.

Воспользуемся уже готовым классом MobileDictionary из предыдущих уроков. Те, кто выполнял их, уже имеют в своем Workbench класс MobileDictionary,

Workbench


те же, кто не выполнял их, смогут импортировать в VAJ готовый файл репозитория (см. ссылку ресурсы в конце статьи). Если же у вас нет VisualAge for Java - я вас поздравляю, вы - настоящий камикадзе, так как решились выполнять этот туториал. В этом случае используйте jar-архив экспорта пакета mdict.vaj35 для доступа к исходному коду упомянутого класса. Перейдите в пакет mdict.jdbc и нажмите кнопку создания нового класса. В качестве суперкласса (родителя) для данного класса выберите mdict.vaj35.MobileDictionary:

Мастер (SmartGuide) создания класса. Шаг 1


Нажмите кнопку Next >.

На втором шаге проверьте, чтобы были включены флажки (checkbox):

  • Copy constructors from superclass (Копировать конструкторы из суперкласса (родительского класса))
  • main() - в этом методе мы будем создавать экземпляр класса MobileDictionaryJDBC
  • finalize() - в этом методе мы будет освобождать ресурсы соединения с БД.
Мастер (SmartGuide) создания класса. Шаг 2


Нажмите кнопку Finish.

Workbench


Скопируйте содержимое метода main из класса MobileDictionary в класс MobileDictionaryJDBC, при этом замените все обращения к типу MobileDictionary на MobileDictionaryJDBC.

Find/Replace диалог


Добавьте:

import java.awt.*;

в начало класса.

Отличия нового класса от старого заключаются в логике его работы:

  • Нам требуется инициализация соединения с БД до первого запроса пользователя (очевидно, единственное доступное место для инициализации соединения - public void loadSettings()).
  • Используем SQL запросы к БД и не используем HTTP прокси сервер (public void performTranslation()).
  • Так как не используется прокси-сервер, то не требуется диалог настройки (пункт меню Edit -> Settings...).

Начнем по порядку. Сначала добавим код инициализации соединения в метод public void loadSettings(). Этот метод вызывается из метода initialize() (в свою очередь вызывается из конструктора), который был создан автоматически VAJ. К сожалению, он имеет модификатор private и является невидимым для своих наследников.

/**
 * 1. Creates DB connection
 * 2. Loads properties from hard disk
 * Creation date: (27.11.01 11:16:39)
 */
public void loadSettings() {

    try {

        Class.forName("org.gjt.mm.mysql.Driver").newInstance();

        try {

            Properties connInfo = new Properties();
            connInfo.put("user", "mdictuser");
            connInfo.put("password", "mdictpassword");
            connInfo.put("useUnicode", "true");
            connInfo.put("characterEncoding", "Cp1251");
            c = DriverManager.getConnection(DBUrl, connInfo);

        } catch (SQLException e) {
            System.out.println("SQLException: " + e.getMessage());
            System.out.println("SQLState:     " + e.getSQLState());
            System.out.println("VendorError:  " + e.getErrorCode());
        }
    } catch (Exception e1) {
        System.err.println("Unable to load driver.");
        e1.printStackTrace();
        System.exit(0);
    }

    super.loadSettings();

}

Не забудьте добавить импорт пакета java.util.* и java.sql.* в начало класса :

/**
 * Graphic JDBC client apllication.
 * Creation date: (27.11.01 14:19:00)
 * @author: Nikolay Zaikin (NZaikin@iba.by)
 */

import java.io.*;
import java.sql.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;

public class MobileDictionaryJDBC
 extends mdict.vaj35.MobileDictionary {

    // URL for connecting via JDBC
    static String DBUrl = "jdbc:mysql://localhost/mdictdb";
    public Connection c;

    // DB tables names
    public String[] tablesNames =
        new String[] {
            "abbrev",
            "computer",
            "economy",
            "general",
            "pc_user",
            "public",
            "rus_eng",
            "update_d" };
    public String resStr = "";
    public Statement s = null;
    public ResultSet rs = null;
    public String queryStr = "";

}

Для явного освобождения ресурсов БД вставьте в метод finalize() следующий код:

   // Insert code to finalize the receiver here.

    // release the DB connection
    if (c != null) {
        c.close();
    }

Теперь вы можете выполнить тестовый запуск программы. Предварительно не забудьте добавить jar архив с классом JDBC драйвера в CLASSPATH VisualAge for Java:

CLASSPATH VisualAge for Java


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

Помняйте в классе MobileDictionary модификаторы переменных:

  • typeDefault
  • wordDefault
  • ivjJWordTextField
с private на public. VisualAge for Java по-умолчанию при графическом проектировании присваивает модификатор private, что является не совсем удобным при наследовании этого класса. Ситуацию могли бы исправить методы getXXXX, но VisualAge for Java также дает им модификаторы private !

Модификатор доступа метода getXXXX


Создадим теперь свой метод public void performTranslation(), который будет перекрывать этот же метод родительского класса и вызываться при нажатии на кнопку Translate !

/**
 * This method composes SQL query,
 * performs translation and
 * outputs the result to the textarea.
 * Creation date: (27.11.01 17:01:31)
 */
public void performTranslation() {

    resStr = "";

    super.outputText("Searching in DB, please wait ...");

    java.util.Date d = new java.util.Date();

    if (ivjJWordTextField.getText().trim().length() > 0) {

        // compose diffrent types of SQL requests
        if (typeDefault == "1") {
            queryStr = " WHERE word LIKE '"
             + ivjJWordTextField.getText() + "%';";
        } else
            if (typeDefault == "2") {
                queryStr = " WHERE word='"
                 + ivjJWordTextField.getText() + "';";
            } else {
                queryStr = " WHERE word LIKE '%"
                 + ivjJWordTextField.getText() + "%';";
            }

        for (int i = 0; i < tablesNames.length; i++) {
            try {
                s = c.createStatement();
                rs = s.executeQuery("SELECT * FROM "
                 + tablesNames[i] + queryStr);
                while (rs.next()) {

                    resStr += rs.getString(1) + "\n";
                    resStr += rs.getString(2);
                    resStr += "\n";
                }

            } catch (SQLException e) {
                System.out.println("SQLException: "
                 + e.getMessage());
                System.out.println("SQLState:     "
                 + e.getSQLState());
                System.out.println("VendorError:  "
                 + e.getErrorCode());
            }
        }

        if (resStr.length() != 0) {
            super.outputText(
                resStr + "searching time: " +
                ((new java.util.Date()).getTime()
                  - d.getTime()) + " mills");
        } else {
            super.outputText("Unknown word. Sorry.");
        }

    } else {
        super.outputText("Please, enter the word.");
    }
}

Попробуйте запустить теперь приложение и простестировать как с английскими, так и с русскими словами. Вы сможете обнаружить, что запрос типа

   SELECT FROM xxxxx WHERE word LIKE '%русское_слово%';

работает некорректно и выдает лишние строки, не соответствующие критерию поиска. Это связано с неправильной установленной кодовой страницей SQL сервера.

Для проверки текущей кодовой страницы выполните команду в консольном клиенте:

mysql> SHOW VARIABLES LIKE '%ch%';

Если вы увидите
| character_set | latin1 |

то это не является правильным. Правильная кодировка для нашего случая - cp1251. Есть несколько решений этой проблемы.

Первое.

Для задания кодировки можно запускать сервер следующей командой :

с:\> mysqld-nt.exe --default-character-set=cp1251

Второе.

Положить в c:\> файл my.cnf - конфигурационный файл MySQL сервера (пример конфигурационного файла можно взять либо в каталоге, куда вы проинсталлировали сервер MySQL - my-example.cnf, либо в системном каталоге Windows после первого запуска winmysqladmin.exe), добавив в него строчку:

[client]
default-character-set=cp1251

После этого запросы типа LIKE '%русское_слово%' будут работать корректно.

Результат работы приложения


В завершение, для отключения пунктов меню Help -> About и Edit -> Settings ... перекройте соответственно методы public void showAboutBox() и public void settings____MenuItem_ActionPerformed(java.awt.event.ActionEvent actionEvent) пустыми методами.

Как всегда, буду рад услышать комментарии и указания на неточности и ошибки по адресу nikolay_zaikin@mail.ru


Ресурсы:

  1. Первый курс статей AWT клиент для веб-приложения
  2. Исходные коды к первому курсу статей (ver. 1.6) в виде исходных файлов и в виде VAJ репозитория.
  3. Исходные коды к первому курсу статей (ver. 1.7) в виде исходных файлов и в виде VAJ репозитория.
  4. Словари в кодировке cp1251.
  5. Исходные коды к данному курсу статей (ver. 1.0) в виде исходных файлов и в виде VAJ репозитория.

TOC




Справка | Условия Copyright © 1999 — 2008, IT • archiv.
В начало | Логин | Комментарий к колонке | Поиск | Почта