InfoCity
InfoCity - виртуальный город компьютерной документации
Реклама на сайте







Размещение сквозной ссылки

 

Доступ к базам даных из Java


Developers.com.ua


Java (не Visual J++) предоставляет доступ к даными при помощи интерфейса JDBC. Данный интерфейс по своей сути напоминает ODBC, более того, в Win32 есть шлюз JDBC-ODBC (хочу предупредить сразу - корректно он работает в семействе win9x, в nt он работает, но ... около минуты, потом GPF :-).

Итак рассмотрим шаги которые необходимо предпринять для того чтобы обработать SQL запрос:

  • Зарегистрировать JDBC-драйвер (на этапе инициализации приложения)
  • Сформировать JDBC-URL-строку для получения соединения с базой.
  • Получить Connection
  • Сформировать SQL запрос
  • Выполнение и обработка SQL-запроса
  • Закрыть полученные соединения (ResultSet, Statament, Connection)

Теперь рассмотрим эти шаги более детально на пример работы с MySql.

Регистрация JDBC-драйвера


Для регистрации драйвера у Вас должны быть:

  • JAR-файл с драйвером должен быть подключен в CLASSPATH'е
  • Вы должны знать название класса-драйвера который вы собираетесь подключать (эту информацию ищите на сайте производителя драйверов. К примеру, покопайтесь в файле readme.txt ;-). Если совсем "в морг" - распакуйте .jar с драйверами и поройтесь в нем - где-то должен быть класс Driver - а потом по вложенности каталогов восстановите название пакета где он лежит).

JAR Вы подключили, теперь надо зарегистрировать драйвер:

String driver="org.gjt.mm.mysql.Driver";

try{
     Class.forName(driver).newInstance();
     DriverManager.registerDriver(
      (Driver)Class.forName(driver).newInstance());

   } catch(Exception e)
     {
       System.out.println("Exception while register driver: "+e);
     }

Формирование JDBC-URL-строки


В наиболее общем случае эта строка имеет вид:

jdbc:id_базы:параметры

В (общем) случае MySql она имеет вид:

jdbc:mysql://хост/база?user=пользователь

Например:

jdbc:mysql://127.0.0.1/GENERAL?user=root

ВНИМАНИЕ! Необходимое отступление по поводу "особенностей" работы лрайверов mysql. Для подключения необходима передача login/password в JDBC драйвер, однако JDBC-драйвера MySql которые мне встречались, вопринимали только login прописанный в строке JDBC-URL и никакими другими способами заставить воспринять драйвер необходимые параметры не получилось.

Получение Connection


Для получения Connection Вы должны вызвать DriverManager.getConnection() и передать во внутрь login/password/jdbc-url:

String url="jdbc:mysql://127.0.0.1/GENERAL?user=root";
String user="";
String password="";
Connection c=null;

try{
     c=DriverManager.getConnection(url,user,password);

   } catch(SQLException e)
     {
       System.out.println("Exception getting connection: "+e);
     }

Формирование SQL запроса


На данном этапе все просто - Вам необходимо сформировать обыкновенную SQL команду, например:

String str="SELECT * FROM MYTABLE";
String str="INSERT INTO MYTABLE (NAME,CNT) VALUES ('"
           +name+"',"+cnt+"')";

Выполнение и обработка SQL-запроса


Для выполнения запроса мы должны у Connection'а получить Statement и вызвать один из его методов в зависимости от типа запроса:

public int executeUpdate(String sql) throws SQLException

Применяется для SQL команд INSERT, UPDATE или DELETE. Возвращает кол-во строк над которыми выполнилась операция.

public ResultSet executeQuery(String sql) throws SQLException

Применяется для SQL команды SELECT. Возвращает ResultSet из которого можно вытянуть информация о шапке таблицы (ResultSetMetaData) и сами значения. Как это делается будет показанно ниже в примере.

public boolean execute(String sql) throws SQLException

Данный метод возвращает true/false - выполнился/не выполнился запрос. Применяется в тех случаях когда SQL запрос возвращает несколько ResultSet'ов. Для их получения используйте getMoreResults().

Пример:

String str="SELECT * FROM RASHOD WHERE USER_ID="+user;
System.out.println(str);

Statement statement = c.createStatement();  // создаем оператор

ResultSet rs = statement.executeQuery(str); // выполняем запрос

ResultSetMetaData md = rs.getMetaData();

int cnt= md.getColumnCount(); // получаем кол-во колонок (1..cnt)

int row=0;

while(rs.next())
{ row++;
  System.out.println("Row "+row);     // вывод номера строки в базе
  for(int i = 1; i <= cnt; i++)
  { String name=md.getColumnName(i);  // получем имя колонки
    String val=rs.getString(i);       // получаем значение
    System.out.println(name+"="+val); // выводим имя и значение поля
  }
}

ВНИМАНИЕ! Применяйте executeUpdate/executeQuery/execute тогда когда они уместны - не вызывайте executeQuery для INSERT'а !!!

Закрытие полученных соединений (ResultSet, Statament, Connection)


Тут все просто - у каждого из них есть метод

close();

Почему так важно закрывать соединения ? Те кто работал с Oracle улыбнутся подобному вопросу - mysql позволяет безболезненно плодить незакрытые соединения (он их сам прибивает со временем), Oracle наоборот - число Connection у него ограниченно (если не ошибаюсь это ограничение на кол-во клиентов), поэтому исчерпав кол-во Connection'ов Вы можете "повесить" свое приложение. Поэтому не стоит приучаться к худшему и затруднять возможную миграцию приложения с MySql на другой SQL-сервер.

Заключение


В заключении хочу рассказать как все это я использую в своих сервлетах. У меня есть класс sql_connection (экземпляр которого создается в init'е) и у которого я получаю Connection'ы:

import java.sql.*;

/**
  * Class for simpling connection to SQL-server's
  * @author General
  */
public class sql_connection
{ private String user;
  private String password;
  private String url;
  private Connection c;
  /**
    * Register specified driver and store user/password/url
    * in internal variables (it need for getConnectio()).
    *
    * @author General
    */
  public sql_connection(String user, String password
                       ,String url,  String driver)
  { this.user=user;
    this.password=password;
    this.url=url;
    try{ Class.forName(driver).newInstance();
         DriverManager.registerDriver(
              (Driver)Class.forName(driver).newInstance());
         c=DriverManager.getConnection(url,user,password);
         c.close();
    } catch(Exception e)
      { System.out.println("Exception while register driver: "+e);}
  }

  /**
    * Return Connectio to SQL-server
    * @return Connection to SQL-server
    * @author General
    */
  final public Connection getConnection()
  { try{ c=DriverManager.getConnection(url,user,password);
       } catch(SQLException e)
         { System.out.println("Exception getting connection: "+e);}
    return(c);
  }

  final protected void finalize()
  { try{ c.close();
       } catch(SQLException e)
    { System.out.println("Exception while close connection: "+e);}
  }
}

Он не завист от имени jdbc драйверов (url, login, password и имя класса вычитываются из ini-файла. Дальше я его применяю следующим образом:

public void view(HttpServletRequest req, HttpServletResponse res)
{ try{ Statement statement = con.getConnection().createStatement();
       String str="SELECT * FROM RASHOD WHERE ID="+id;
       System.out.println(str);
       ResultSet rs = statement.executeQuery(str);
       ResultSetMetaData md = rs.getMetaData();
       int cnt= md.getColumnCount();

       while(rs.next())
       { for(int i = 1; i <= cnt; i++)
         { String name=md.getColumnName(i);
           String val=rs.getString(i);
           ...
         }
       }

       rs.close();
       statement.close();
       res.setContentType(conf.CONTENT_TYPE);
       PrintWriter out = res.getWriter();
       ...

     } catch(Exception e) {System.out.println(""+e);}
}

И еще пару слов о необходимости Connection pool. Это такая вещь которая кеширует соединения с базами - например в сервлетах слишком долго каждый раз устанавливать соединения, или например в Oracle ограничение на кол-во одновременно открытых соединений. Поэтому Вам следует подумать над ее использванием. К примеру в вебсервере jakarta tomcat реализован такой pool.


Реклама на InfoCity

Яндекс цитирования



Финансы: форекс для тебя








1999-2009 © InfoCity.kiev.ua