Разработка мобильного словаря с использованием JDBC. Часть 5
(Николай Зайкин)
5. Создание графического клиентского JDBC приложения.
Писать аналогичное приложение (как для доступа к CGI скриптам через web) с нуля не
совсем разумно, так как это достаточно большая задача. Ей был посвящен целый
курс статей.
Воспользуемся уже готовым классом MobileDictionary из
предыдущих уроков. Те, кто выполнял их,
уже имеют в своем Workbench класс MobileDictionary,
те же, кто не выполнял их, смогут импортировать в VAJ готовый файл репозитория (см.
ссылку ресурсы в конце статьи). Если же у вас нет VisualAge for Java - я вас поздравляю,
вы - настоящий камикадзе, так как решились выполнять этот туториал. В этом случае
используйте jar-архив экспорта пакета mdict.vaj35 для доступа к исходному
коду упомянутого класса. Перейдите в пакет mdict.jdbc и нажмите кнопку
создания нового класса. В качестве суперкласса (родителя) для данного класса выберите
mdict.vaj35.MobileDictionary:
Нажмите кнопку Next >.
На втором шаге проверьте, чтобы были включены флажки (checkbox):
- Copy constructors from superclass (Копировать конструкторы из суперкласса
(родительского класса))
- main() - в этом методе мы будем создавать экземпляр класса
MobileDictionaryJDBC
- finalize() - в этом методе мы будет освобождать ресурсы соединения с БД.
Нажмите кнопку Finish.
Скопируйте содержимое метода main из класса MobileDictionary
в класс MobileDictionaryJDBC, при этом замените все обращения к типу
MobileDictionary на MobileDictionaryJDBC.
Добавьте:
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:
Из-за чрезмерной защищенности родительского класса мы не можем получить доступ к
настройкам интерфейса. Это является ошибкой проектирования родительского класса, но он не
подразумевался для наследования. При написании своих классов, старайтесь предусмотреть
возможность наследования.
Помняйте в классе MobileDictionary модификаторы переменных:
- typeDefault
- wordDefault
- ivjJWordTextField
с private на public. VisualAge for Java по-умолчанию при графическом проектировании
присваивает модификатор private, что является не совсем удобным при наследовании этого
класса. Ситуацию могли бы исправить методы getXXXX, но VisualAge for Java также дает им
модификаторы private !
Создадим теперь свой метод 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
Ресурсы:
- Первый курс статей AWT клиент для
веб-приложения
- Исходные коды к первому курсу статей (ver. 1.6) в виде
исходных файлов и в виде
VAJ репозитория.
- Исходные коды к первому курсу статей (ver. 1.7) в виде
исходных файлов и в виде
VAJ репозитория.
- Словари в кодировке cp1251.
- Исходные коды к данному курсу статей (ver. 1.0) в виде
исходных файлов и в виде
VAJ репозитория.
TOC
|