div.main {margin-left: 20pt; margin-right: 20pt}
Доступ к базам даных из 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.
Для регистрации драйвера у Вас должны быть:
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:id_базы:параметры
В (общем) случае MySql она имеет вид: jdbc:mysql://хост/база?user=пользователь
Например: jdbc:mysql://127.0.0.1/GENERAL?user=root
ВНИМАНИЕ! Необходимое отступление по поводу
"особенностей" работы лрайверов mysql. Для подключения необходима передача
login/password в JDBC драйвер, однако JDBC-драйвера MySql которые мне
встречались, вопринимали только login прописанный в строке JDBC-URL и
никакими другими способами заставить воспринять драйвер необходимые
параметры не получилось.
Для получения 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 команду, например: String str="SELECT * FROM MYTABLE";
String str="INSERT INTO MYTABLE (NAME,CNT) VALUES ('"
+name+"',"+cnt+"')";
Для выполнения запроса мы должны у 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'а !!!
Тут все просто - у каждого из них есть метод 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.
|