Rambler's Top100IT • archiv

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




Колонки


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

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

4. Загрузка и проверка таблиц словарей в БД.

Для создания нового класса FilesLoader используем элементы предыдущий двух классов: FilesTester и GetConnection.

Чтобы не создавать новый класс с нуля, воспользуемся старым классом FilesTester и скопируем его с переименованием:

  1. Установите курсор на класс FilesTester. Нажмите правую кнопку мыши Reorganize -> Copy... Либо через меню Selected -> Reorganize -> Copy...
  2. Выберите имя нового класса (FilesLoader):
    Копирование классов

Сразу же исправьте в методе main строку создания экземпляра класса на:

 new FilesLoader(dirName);

Основные изменения будут проводиться в конструкторе FilesLoader().

Для введения соответствия между именами файлов словарей на жестком диске и именами таблиц в базе данных, создадим объект типа java.util.Properties:

Properties tableProps = new Properties();
tableProps.setProperty("abbrev.dict", "abbrev");
tableProps.setProperty("computer.dict", "computer");
tableProps.setProperty("economy.dict", "economy");
tableProps.setProperty("general.dict", "general");
tableProps.setProperty("pc-user.dict", "pc_user");
tableProps.setProperty("public.dict", "public");
tableProps.setProperty("rus-eng.dict", "rus_eng");
tableProps.setProperty("update.dict", "update_d");

Не забудьте добавить строчку:

import java.util.*;

в начало класса FilesLoader(), иначе VisualAge for Java не сможет выполнить инкрементное компилирование класса после нажатия Ctrl+S.

Аналогично импортируйте в класс пакет java.sql.*.

Так как файлы словарей у нас содержат русские символы в кодировке CP1251, нам следует сообщить это базе данных. Это выполняется на этапе установки соединения с БД с помощью нового синтаксиса, который мы еще не рассматривали:

static String DBUrl = "jdbc:mysql://localhost/mdictdb";
....
Properties connInfo = new Properties();
connInfo.put("user", "root");
connInfo.put("password", "rootpassword");
connInfo.put("useUnicode", "true");
connInfo.put("characterEncoding", "Cp1251");
Connection c = DriverManager.getConnection(DBUrl, connInfo);

Для занесения данных в БД используется SQL запрос типа

INSERT INTO table_name(word, translation)
 VALUES (value1, value2);

Для ускорения работы программы и экономии ресурсов (памяти) применим класс PreparedStatement. В отличие от Statement, он предварительно обрабатывается СУБД или JDBC драйвером, что позволяет сэкономить время на трансляцию запроса и хранится в прекомпилированном виде, мы только задаем новые параметры новыми переменным (value1, value2) и вызываем запуск запроса.

Этот тип выражения обычно используется для многократных подобных SQL запросов, имеющих незначительные отличия (во входных параметрах). Например, при загрузке данных.

Входные параметры обозначаются с помощью вопросительного знака. И перед выполнением запроса их значения должны быть установлены методами setXXXX().

В Java синтаксисе это схематично выглядит так:

Connection c =
DriverManager.getConnection(DBUrl, connInfo);
PreparedStatement prepStmt = null;
....
prepStmt = c.prepareStatement(
 "INSERT INTO " + tableProps.getProperty(s[i])
  + "(word,translation) VALUES (?, ?)");
....
prepStmt.setString(1, word);
prepStmt.setString(2, current);
prepStmt.execute();

Обратите внимание, что отсчет номеров столбцов в методах setXXXX() начинается с единицы, а не с нуля.

Полный листинг класса FilesLoader приведен ниже, скопируйте из него недостающие методы в ваш IDE и попробуйте запустить на выполнение.

package mdict.jdbc;

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

/**
 * This class loads data from flat text files into MySQL tables.
 * Creation date: (15.11.01 17:38:58)
 * @author: Mikalai Zaikin (NZaikin@iba.by, MZaikin@de.ibm.com)
 */
public class FilesLoader implements FilenameFilter {

    static String DBUrl = "jdbc:mysql://localhost/mdictdb";
/**
 * This method loads data from flat text files into MySQL tables.
 * Creation date: (16.11.01 9:20:09)
 */
public FilesLoader(String dirName) {

    Properties tableProps = new Properties();
    tableProps.setProperty("abbrev.dict", "abbrev");
    tableProps.setProperty("computer.dict", "computer");
    tableProps.setProperty("economy.dict", "economy");
    tableProps.setProperty("general.dict", "general");
    tableProps.setProperty("pc-user.dict", "pc_user");
    tableProps.setProperty("public.dict", "public");
    tableProps.setProperty("rus-eng.dict", "rus_eng");
    tableProps.setProperty("update.dict", "update_d");

    File d = new File(dirName);

    String s[] = d.list(this);

    if (s == null) {
        System.out.println("Incorrect directory name '" + dirName + "'.");
        System.exit(0);
    }

    if (s.length == 0) {
        System.out.println("Directory '" + dirName + "' is empty.");
        System.exit(0);
    }

    FileReader fileInStream;
    BufferedReader dataInStream;
    String result = "";
    boolean isWord = true;
    boolean firstLine = true;
    int maxLength = 0;
    String current = "";
    String word = "";

    try {
        Class.forName("org.gjt.mm.mysql.Driver").newInstance();
        System.out.println("JDBC driver loaded !");

        Properties connInfo = new Properties();
        connInfo.put("user", "root");
        connInfo.put("password", "rootpassword");
        connInfo.put("useUnicode", "true");
        connInfo.put("characterEncoding", "Cp1251");

        Connection c = DriverManager.getConnection(DBUrl, connInfo);
        PreparedStatement prepStmt = null;

        for (int i = 0; i < s.length; i++) {

            prepStmt =
                c.prepareStatement(
                    "INSERT INTO " + tableProps.getProperty(s[i])
                     + "(word,translation) VALUES (?, ?)");

            try {
                fileInStream = new FileReader(dirName
                 + File.separator + s[i]);
                dataInStream = new BufferedReader(fileInStream);

                while ((result = dataInStream.readLine()) != null) {

                    isWord = (result.trim().length() == 0);

                    if (isWord) {
                        prepStmt.setString(1, word);
                        prepStmt.setString(2, current);
                        prepStmt.execute();
                        current = "";
                        // first line will be a word
                        firstLine = true;
                    } else {
                        // check for word (first line)
                        // we don't need to count word length,
                        // only translation length
                        if (firstLine) {
                            firstLine = false;
                            word = result.trim(); 
                             // get word into variable
                        } else {
                            // add rarriage return characters, 
                            // because readLine() method trim them
                            current += result + "\r\n";
                        }

                    }

                }
                fileInStream.close();
                dataInStream.close();
                System.out.println("Table '" +
                 tableProps.getProperty(s[i]) + "' filled.");
            } catch (Throwable exc) {
                exc.printStackTrace(System.out);
            }
        }
        System.out.println("Done.");

        c.close(); // close DB connection

    } catch (Exception ex) {
        ex.printStackTrace(System.out);
    }

}
/**
 * This method perform verification of file name.
 * It returns true if the file has dictionary extension (.dict),
 * otherwise it returns false.
 * This method is required because class FilesLoader implements
 * FilenameFilter interface.
 * Creation date: (15.11.01 18:12:50)
 * @return boolean
 * @param fil java.io.File
 * @param name java.lang.String
 */

public boolean accept(File dir, String name) {
    if (name.endsWith("dict") && (new File(dir, name)).isFile()) {
        return true;
    }

    return false;
}
/**
 * Starts the application.
 * @param args an array of command-line arguments
 */
public static void main(java.lang.String[] args) {

    String dirName = ".";
    if (args.length > 0) {
        dirName = args[0];
    }

    new FilesLoader(dirName);

}
}


Попробуйте запустить новый класс на выполнение. Если вы получите исключительную ситуацию типа "Класс org.gjt.mm.mysql.Driver не найден", это означает, что VisualAge не может найти класс JDBC драйвера.

Дело в том, что VisualAge for Java использует свой встроенный IBM JDK, и не оспользует системную переменную окружения %CLASSPATH%. Для прописывания класса драйвера в переменную CLASSPATH VisualAge for Java сделайте следующее:

  1. Нажмите мышкой на класс FilesLoader.
  2. Выберите в меню Selected -> Run -> Check Class Path (это же можно сделть через контекстное меню по правой кнопке мышки).
  3. В Extra directories path поставьте птичку и пропишите в текстовом поле путь к jar-архиву драйвера (mm.mysql-2.0.7-bin.jar):

    Добавление классов в CLASSPATH VisualAge for Java

Запустите снова класс на выполнение.

Таблицы должны заполниться данными (вы сможете узнать об этом по мере вывода сообщений):

Вывод программы FilesLoader

Для проверки правильности занесенных данных напишем простейший класс DataTester (этот класс надо запускать именно из VisualAge for Java, так как Windows консоль использует кодировку MS-DOS - CP866, и при запуске тестовго класса не из графического приложения вы получите на экране неразбериху, хотя на самом деле, данные буду храниться и выбираться в правильной кодировке):

package mdict.jdbc;

import java.sql.*;
import java.util.*;


public class DataTester {
    static String DBUrl = "jdbc:mysql://localhost/mdictdb";
public static void main(String[] Args) {
    try {

        Class.forName("org.gjt.mm.mysql.Driver").newInstance();
        System.out.println("Driver loaded !");
        try {

            Properties connInfo = new Properties();
            connInfo.put("user", "root");
            connInfo.put("password", "rootpassword");
            connInfo.put("useUnicode", "true");
            connInfo.put("characterEncoding", "Cp1251");
            Connection c = DriverManager.getConnection(DBUrl, connInfo);
            System.out.println("Connection Created !");

            Statement s = c.createStatement();
            ResultSet rs = s.executeQuery(
             "SELECT * FROM abbrev WHERE word LIKE 'l%';");
            while (rs.next()) {
                System.out.println("--------------------------------");
                System.out.println(rs.getString(1));
                System.out.println(rs.getString(2));
            }

            c.close();
        } 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();
    }
}
}


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

Вывод программы должен показать следующий результат.

Вывод программы DataTester

Если вывод вашей программы совдает, то вы можете переходить к следующему этапу - написанию графического клиентского приложения.

Если в процессе загрузки данных у вас произошел сбой, вы сможете быстро очистить все таблицы, скопировав нижеприведенный код:

USE mdictdb;

DELETE FROM abbrev;
DELETE FROM computer;
DELETE FROM economy;
DELETE FROM general;
DELETE FROM pc_user;
DELETE FROM public;
DELETE FROM rus_eng;
DELETE FROM update_d;

в текстовый файл (назовите его, например clear.sql), и запустив файл на выполнение командой:
mysql> \. clear.sql

TOC | Часть 5 >




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