MySQL & mSQL

Что такое JDBC?


Как и все Java API, JDBC является набором классов и интерфейсов, в совокупности поддерживающих определенный набор функций. В случае JDBC эти функции обеспечивают доступ к базе данных. Классы и интерфейсы, составляющие JDBC API, являются, таким образом, абстракциями понятий, общих при доступе к базам данных любого типа. Например, Connection является интерфейсом Java, представляющим соединение с базой данных. Аналогично ResultSet представляет результирующий набор данных, возвращаемый командой SQL SELECT. Классы, образующие JDBC API, находятся в пакете Java, sql, который был введен Sun в JDK 1.1.

Естественно, что конкретные детали доступа к базе данных зависят от ее изготовителя. JDBC фактически не имеет дела с этими деталями. Большая часть классов в пакете Java.sql является интерфейсами без реализации. Реализация этих интерфейсов осуществляется производителем базы данных в виде драйвера JDBC. В качестве программиста баз данных вам нужно знать очень немногое относительно драйвера, который вы используете, — все остальное делается через интерфейсы JDBC. Специфическая информация о базе данных, которая необходима для использования JDBC, включает в себя:

  • URL для драйвера JDBC.

  • Имя класса, реализующего Java. sql. Driver.

    В новую спецификацию JDBC 2.0 включено необязательное для реализации производителями баз данных стандартное расширение API. Если поставщик вашей базы данных JDBC реализовал это стандартное расширение, вам даже нет необходимости знать JDBC URL или реализацию класса Driver. Это расширение предусматривает наличие класса DataSource, который можно найти по имени в каталоге с поддержкой JNDI.

    Оба эти элемента можно получить во время выполнения - из командной строки или файла свойств. Сам код программы не ссылается на эти два зависящие от реализации элемента. Мы разъясним, что делают JDBC URL и класс Driver в тех параграфах, где будем рассказывать о соединении с базами данных. На рисунке 14-1 представлена схема интерфейсов JDBC.

    JNDI - Java Naming and Directory Interface (интерфейс имен и каталогов Java) API. Он позволяет запоминать объекты Java в службе имен и каталогов, такой как сервер Lightweight Directory Access Protocol (облегченный протокол доступа к каталогам - LDAP), и находить их по имени.




    Рис. 14-1. Классы и интерфейсы, входящие в JDBC API

    Соединение с базой данных

    Прежде всего нужно соединиться с базой данных. Один из немногих реализованных в пакете Java. sql. package классов - это класс DriverManager. Он поддерживает список реализаций JDBC и обеспечивает создание соединений с базами данных на основе сообщаемых ему JDBC URL. URL для JDBC имеет вид jdbc:protocol:subprotocol. Он сообщает DriverManager, с какой СУБД нужно соединиться, и передает ему данные, необходимые для осуществления соединения.

    Смысл слова «driver» в JDBC зависит от контекста. При написании в нижнем регистре JDBC driver является собранием классов, в совокупности реализующих все интерфейсы JDBC и обеспечивающих приложение доступом хотя бы к одной базе данных. При написании Driver с заглавной буквы подразумевается класс, реализуемый в Java. sql. Driver. И наконец, JDBC предоставляет интерфейс DriverManager, с помощью которого можно вести учет всех различных реализаций Driver.



    Часть URL, обозначающая протокол, ссылается на конкретный драйвер JDBC. В случае MySQL и mSQL протоколами являются ту sql и msql соответственно. Субпротокол сообщает данные соединения, специфические для реализации. Для соединения с MySQL и mSQL требуются имя узла и имя базы данных. Дополнительно может потребоваться номер порта, если ядро базы данных запущено не как root. Поэтому полный URL для mSQL выглядит как, например, jdbc:msql://athens.imagi-nary.com: 1114/test. Он сообщает DriverManager о необходимости найти драйвер JDBC для mSQL и соединиться с базой данных test на athens.imaginary.com через порт 1114. Это делается путем единственного обращения к методу getConnection() интерфейса DriverManager. В примере 14-1 показано, как осуществить соединение с базой данных mSQL.

    Пример 14-1. Отрывок кода из примеров, предоставляемых с драйвером JDBC для mSQL, показывающий, как осуществить соединение

    import java.sql.*;

    public class Connect { public static void main(String argv[]) {

    Connection con = null;



    try {

    // Вот JDBC URL для этой базы данных

    String url = "jdbc:msql://athens.imaginary.com:1114/db_test";

    // 0 том, что делают классы Statement и ResultSet, ниже Statement stmt; ResultSet rs;

    // передать это как свойство, т.е.

    // -Djdbc.drivers=com.imaginary.sql.msql.MsqlDriver

    // или загрузить, как сделано в этом примере

    Class.fоrName("com.imaginary, sql. msql. MsqlDriver");

    // здесь осуществляется соединение

    con = DriverManager.getConnection(url, "borg", "");

    }

    catch( SQLException e ) {

    e.printStackTrace(); }

    finally {

    if( con != null ) {

    try { con.close();

    }

    catch( Exception e ) { }

    }

    }

    }

    }

    В этом примере соединение с базой данных осуществляется в строке con=DriverManager.getConnection(url, "borg", ""). В данном случае JDBC URL и имя класса, реализующего Driver, фактически введены в код приложения. В демонстрационной программе это допустимо, но всякое серьезное приложение должно загружать эти данные из файла свойств, получать через аргументы командной строки или из свойств системы. Реализация Driver будет автоматически загружена, если передать ее как системное свойство jdbc.drivers - иными словами, не нужно вызывать Class. ForName(). newlnstance(driver_name), если вы передаете имя драйвера как системное свойство jdbc.drivers. Второй и третий аргументы getConnection() передают ID пользователя и пароль, необходимые для установления соединения. Поскольку mSQL не использует пароли для авторизации пользователей, в примере используется пустая строка. Для MySQL же необходимо сообщить пароль.

    Поддержка переносимости с помощью файлов свойств

    Хотя наше внимание сосредоточено на двух конкретных базах данных, хорошей практикой программирования на Java является обеспечение полной переносимости приложений. Под переносимостью обычно подразумевается, что вы не пишете код, предназначенный для выполнения только на какой-то одной платформе. Однако для Java термин «переносимость» имеет более сильный смысл. Он означает независимость от аппаратных ресурсов и независимость от базы данных.



    Мы сказали о том, что JDBC URL и имя Driver зависят от реализации, но не сказали, как избежать их включения в код. Поскольку и то, и другое представляет собой простые строки, их можно передать в качестве параметров командной строки или как параметры апплетов. Это работающее, но едва ли элегантное решение, поскольку оно требует, чтобы пользователь помнил длинные командные строки. Аналогичное решение - выдавать пользователю приглашение для ввода этих данных, которое опять-таки требует, чтобы пользователь вспоминал JDBC URL и имя класса Java при каждом запуске приложения.

    Более изящное решение получается при использовании файла свойств. Файлы свойств поддерживаются классом Java. util. Resource-Bundle и его подклассами, позволяя приложению извлекать данные, относящиеся ко времени исполнения, из текстового файла. Для приложения, использующего JDBC, можно вставить в файл свойств URL и имя Driver, возложив на администратора приложения обязанность указать детали соединения. Пример 14-2 показывает файл свойств,

    предоставляющий данные о соединении.

    Пример 14-2. Файл SelectResource.properties с подробностями соединения

    Driver=com.imaginary.sql.msql.MsqlDriver

    URL=jdbc:msql://athens.imaginary.com:1114/db_test

    В примере 14-3 показан переносимый класс Connection.

    Пример 14-3. Специфические данные

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

    public class Connect {

    public static void main(String argv[]) {

    Connection con = null;

    ResourceBundle bundle = ResourceBundle.getBundle("SelectResource");

    try {

    String url = bundle.getString("URL");

    Statement stmt; ResultSet rs;

    Class.forName(bundle.getString("Driver")); // здесь осуществляется соединение

    con = DriverManager.getConnection(url, "borg", ""); }

    catch( SQLException e ) { e. printStackTrace();

    }

    finally

    {

    if( con != null )

    {

    try { con.close(); }

    catch( Exception e ) { }

    }

    }

    }

    }

    В этом примере установления соединения мы избавились от кода, специфичного для mSQL. Однако для разработчиков переносимых JDBC-приложений остается одна важная проблема, особенно касающаяся тех, кто работает с mSQL. JDBC требует, чтобы все драйверы поддерживали начальный уровень (entry level) SQL2. Это стандарт ANSI минимальной поддержки SQL. Если при вызовах JDBC вы поддерживаете начальный уровень SQL2, то ваше приложение будет стопроцентно переносимо на другие базы данных. MySQL поддерживает минимальный уровень SQL2, a mSQL - увы, нет. Приложения, написанные для mSQL, скорее всего, без проблем будут переноситься на другие базы данных, но приложения, написанные с использованием начального уровня SQL92, в полном объеме нельзя будет безболезненно перенести обратно на mSQL.




    Содержание раздела