JDBC Работа СУБД Oracle JDBC JDBC – прикладной программный интерфейс (API) для выполнения SQL-запросов. Состоит из множества классов и интерфейсов, написанных на JAVA. Преимущества: 1. 2. 3. 4. Легкость отсылки запросов.

Download Report

Transcript JDBC Работа СУБД Oracle JDBC JDBC – прикладной программный интерфейс (API) для выполнения SQL-запросов. Состоит из множества классов и интерфейсов, написанных на JAVA. Преимущества: 1. 2. 3. 4. Легкость отсылки запросов.

Slide 1

JDBC
Работа СУБД Oracle


Slide 2

JDBC
JDBC – прикладной программный интерфейс
(API) для выполнения SQL-запросов.
Состоит из множества классов и
интерфейсов, написанных на JAVA.
Преимущества:
1.

2.

3.

4.

Легкость отсылки запросов на сервер БД
Использование JDBC API освобождает от
написания приложения для каждой БД
Поддержка всех расширений (типов,
соединений, классов…) СУБД. Соответствие
SQL (но, как всегда, есть исключения)
…….


Slide 3

Что может JDBC
Устанавливать соединения с БД,
используя различные типы
подключений
 Отсылать SQL-запросы
 Обрабатывать результаты



Slide 4

JDBC драйверы, поставляемые Oracle








Thin Driver – драйвер для создания клиентских
приложений, не требующий установки клиента
Oracle.
OCI Drivers - драйвер для создания клиентских
приложений, требующий установки клиента Oracle
(OCI 7, 8).
Server-side Thin Driver – драйвер,
функциональность которого как у Thin Driver, но
применяется для выполнения кода внутри СУБД. Код
может подключаться к удаленной СУБД или
реализовывать 3-х звенные приложения.
Server-side Internal Driver – драйвер,
применяющийся при создании приложений внутри
СУБД. Исполняет хранимые Java-процедуры и
подключается к ядру СУБД, на которой работает.


Slide 5

Структура


Slide 6

Thin Driver









Драйвер на 100% написан на Java. Предназначен
для апплетов, но годится и для клиентских
приложений.
Драйвер платформонезависимый, не требует
клиента СУБД.
Закачивается браузером и начинает работу вместе
с апплетом.
Драйвер обеспечивает прямое соединение с СУБД
через стек TCP/IP путем эмуляции работы
библиотеки OCI8 и TTC.
Со стороны СУБД обязательно должен быть
Listener.
Для работы с этим типом драйвера в браузере д.б.
разрешена поддержка Java-сокетов.


Slide 7

OCI Driver





Драйвер написан на Java и Си. Предназначен для
создания клиентских приложений.
Требует установки клиента Oracle и является
платформозависимым.
Драйвер переводит JDBC-вызовы в вызовы OCI.
Использует библиотеки OCI8, Net8, Core …
Предоставляет широкую совместимость с
различными версиями СУБД (7,8i,9,10), а также
более широкие возможности по работе с СУБД –
named pipe …


Slide 8

Выбор соответствующего драйвера
При написании апплетов используется
только Thin Driver (OCI не работает из-за
вызовов Си)
 Для обеспечения максимальной
производительности в клиентском
приложении используется OCI Driver.
 При написании 3-х звенных приложений
используется server-side Thin Driver.
 Если код создаваемого приложения будет
работать внутри СУБД, то используется
server-side internal Driver.



Slide 9

Последовательность действий
Для того чтобы подключиться к СУБД и выполнить запрос,
необходимо написать код для выполнения следующих
действий:
1.
2.
3.
4.
5.
6.
7.
8.

9.
10.

Import Packages
Register the JDBC Drivers
Open a Connection to a Database
Create a Statement Object
Execute a Query and Return a Result Set Object
Process the Result Set
Close the Result Set and Statement Objects
Make Changes to the Database
Commit Changes
Close the Connection


Slide 10

Шаг 1. Import Packages
import java.sql.*; // стандартный пакет JDBC
import oracle.jdbc.driver.*; // расширение JDBC для
Oracle
import oracle.sql.*; // особенности языка SQL для
Oracle
Необходимо переменной classpath указать
положение драйвера JDBC
([ORACLE_HOME\jdbs\lib\zip-классы]). Сделать
это можно 2 способами:






1.
2.

через переменную среды окружения
при компиляции и запуске указать ключ javac -classpath
".; ORACLE_HOME\jdbs\lib\classes12.zip;
ORACLE_HOME\jdbs\lib\nls_charset12.zip"


Slide 11

Шаг 2. Register the JDBC Drivers
Данная операция осуществляется
вызовом статического метода:
DriverManager.registerDriver(new
oracle.jdbc.driver.OracleDriver());




Slide 12

Шаг 3.Open a Connection to a Database(1)


Для открытие соединения вызывается метод getConnection()
класса DriverManager, возвращающий объект типа
Connection.

getConnection(String URL, String user, String
password);
Строка URL выглядит следующим образом:
jdbc:oracle::@.
Например,
DriverManager.getConnection
("jdbc:oracle:thin:@myhost:1521:orcl", "scott",
"tiger");
или
DriverManager.getConnection("jdbc:oracle:oci8:@(descript
ion=(address=(host=myhost)(protocol=tcp)(port=1521))(
connect_data=(sid=orcl)))","scott", "tiger");

Connection
conn=DriverManager.getConnection("jdbc:oracle:oci8:@mics",
"stud01", "stud01");


Slide 13

Шаг 3.Open a Connection to a Database(2)
Следующий вариант метода представлен ниже, где
строка URL включает в себя имя пользователя и
пароль
getConnection(String URL);
URL есть:
jdbc:oracle::/@base>
Например,
DriverManager.getConnection
("jdbc:oracle:oci8:scott/tiger@myhost);

или
DriverManager.getConnection
("jdbc:oracle:thin:scott/tiger@myhost:1521:orcl);


Slide 14

Шаг 3.Open a Connection to a Database(3)
Для передачи дополнительных параметров в строку
соединения используется объект Properties.
getConnection(String URL, Properties
info);
где URL:
jdbc:oracle::@
Например,
java.util.Properties info = new
java.util.Properties();
info.put ("user", "scott");
info.put ("password","tiger");
info.put ("defaultRowPrefetch","15");
info.put ("internal_logon","sysdba");
getConnection ("jdbc:oracle:oci8:@",info);


Slide 15

Шаг 4. Create a Statement Object
Создание объекта Statement для описания запроса
используется метод createStatement класса
соединения
Statement stmt = conn.createStatement();


Slide 16

Шаг 5. Execute a Query and Return a Result Set
Object
Для выполнения запроса к БД используется метод
executeQuery класса Statement. Полученный
резульат возвращается в переменную класса
ResultSet, которую в дальнейшем
необходимо обработать.
ResultSet rset = stmt.executeQuery
("SELECT ename FROM emp");


Slide 17

Шаг 6. Process the Result Set




После получения данных в переменную ResultSet
необходимо вызывать метод next() для построчного доступа к
данным до тех пор, пока не будет достигнут конец данных.
Для извлечения данных используется метод getXXX() класса
ResultSet, где XXX – предопределенный тип Java.
while (rset.next())
System.out.println (rset.getString(1));


Slide 18

Шаг 7. Close the Result Set and Statement
Objects





Необходимо после использования явно закрывать
экземпляры типов Statement и ResultSet вызовом метода
close().
Драйвер не содержит метод finalizer(), поэтому очистка
памяти происходит при вызове close().
Если переменная rset имеет тип ResultSet, а stmt – Statement,
то
rset.close();
stmt.close();


Slide 19

Шаг 8. Make Changes to the Database




Для записи данных в базу через операции Insert или Update
используется класс PreparedStatement. Объект данного
класса позволяет выполнить выражение с переменным
числом входных параметров.
Для подстановки значений в выражение PreparedStatement
используется метод setXXX() класса PreparedStatement.

Например,
PreparedStatement pstmt =
conn.prepareStatement ("insert into EMP (EMPNO, ENAME) values (?, ?)");
// Add LESLIE as employee number 1500
pstmt.setInt (1, 1500); // The first ? is for EMPNO
pstmt.setString (2, "LESLIE"); // The second ? is for ENAME
// Do the insertion
pstmt.execute ();


Slide 20

Шаг 9. Commit Changes






По умолчанию, операции DML (Insert, Update, Delete)
фиксируются автоматически после их выполнения. Для
отключения такого режима используется команда
conn.setAutoCommit(false);
Если автоматический режим отключен, то необходимо
вручную выполнять операции commit и rollback:
conn.commit() или
conn.rollback()
Неявный commit всегда срабатывает при разрыве
соединения или выполнении функций DDL.


Slide 21

Шаг 10. Close the Connection


После завершения работы необходимо закрыть соединение
conn.close()


Slide 22

Пример
import java.sql.*; import java.io.*; import java.awt.*;
class JdbcTest {
public static void main (String args []) throws SQLException {
// Load Oracle driver
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection
("jdbc:oracle:thin:@myhost:1521:ORCL","scott", "tiger");
// Query the employee names
Statement stmt = conn.createStatement ();
ResultSet rset = stmt.executeQuery ("SELECT ename FROM emp");
while (rset.next ())
System.out.println (rset.getString (1));
//close the result set, statement, and the connection
rset.close(); stmt.close(); conn.close();
}
}


Slide 23

Выражение Statement
Бывает 3 видов:
 Statement – для выполнения запросов Select
 PreparedStatement – для операций DDL и DML,
добавляет методы управления входными (IN)
параметрами.
 CallableStatement – для вызова хранимых
процедур, добавляет методы для манипуляции
выходными (OUT) параметрами.
Методы выполнения выражений:
 executeQuery()
 executeUpdate()
 execute()


Slide 24

Выражение Statement



Объект Statement используется для выполнения
SQL-запросов к БД.
Предоставляет базовые методы для выполнения
запросов и извлечения результатов в Result Set.

Connection con = DriverManager.getConnection(url, "sunny", "");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table");


Slide 25

Prepared Statement


Интерфейс PreparedStatement наследует от
Statement и отличается от последнего следующим:





Экземпляры PreparedStatement "помнят"
скомпилированные SQL-выражения.
SQL-выражения в PreparedStatement могут иметь один
или более входной (IN) параметр.

Входной параметр - это параметр, чье значение не
указывается при создании SQL-выражения. Вместо
него в выражении на месте каждого входного
параметра ставится знак ("?"). Значение каждого
вопросительного знака устанавливается методами
setXXX перед выполнением запроса.


Slide 26

Создание Prepared Statement


Поскольку объекты PreparedStatement прекомпилированны,
исполнение этих запросов может происходить несколько
быстрее, чем в объектах Statement.



Создание объекта PreparedStatement выполняется вызовом
метода prepareStatement, который сразу отправляет запрос
на СУБД и подготавливает его для выполнения

PreparedStatement pstmt = con.prepareStatement( "UPDATE table4
SET m = ? WHERE x = ?");


Slide 27

Передача входных параметров




Перед выполнением объекта PreparedStatement надо
установить значения всех его параметров. Это делается с
помощью методов setXXX, где XXX - это тип параметра.
Например,
pstmt.setLong(1, 123456789); pstmt.setLong(2, 100000000);
После установки параметра его можно использовать при
многократном выполнении выражения до тех пор, пока он не
очистится методом clearParameters. Один и тот же объект
PreparedStatement может выполняться много раз, если
нижестоящий драйвер или СУБД будут сохранять выражение
(statement) в открытом состоянии даже после того как
произойдет commit.
pstmt.setString(1, "Hi");
for (int i = 0; i < 10; i++) {
pstmt.setInt(2, i);
int rowCount = pstmt.executeUpdate(); }


Slide 28

import java.sql.*;
class InsertExample
{
public static void main (String args []) throws SQLException
{ DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
String url = "jdbc:oracle:oci8:@mics";
Connection conn = DriverManager.getConnection (url, "stud01", “stud01");
Statement stmt = conn.createStatement ();

try
{stmt.execute ("delete from EMP where EMPNO = 1500"); }
catch (SQLException e) {… }
stmt.close();
PreparedStatement pstmt = conn.prepareStatement ("insert into EMP (EMPNO,
ENAME) values (?, ?)");
// Add LESLIE as employee number 1500
pstmt.setInt (1, 1500);
// The first ? is for EMPNO
pstmt.setString (2, "LESLIE"); // The second ? is for ENAME
// Do the insertion
pstmt.execute ();
pstmt.close();
conn.close(); }
}

Метод setNull позволяет отсылать значения NULL в БД как входные параметры.


Slide 29

Callable Statement (вызываемый оператор)
Объект CallableStatement предоставляет унифицированный
способ вызова хранимых процедур в любой СУБД.
Синтаксис вызова:
CallableStatement cs1 = conn.prepareCall ( "{call proc (?,?)}" ) ; //
вызов хранимой процедуры
CallableStatement cs2 = conn.prepareCall
( "{? = call func (?,?)}" ) ; // вызов функции


Для PL/SQL вид следующий:
CallableStatement cs3 = conn.prepareCall ( "begin proc (?,?); end;" )
CallableStatement cs4 = conn.prepareCall ( "begin ? := func(?,?);end;")


Знаки ? могут быть как входными, так и выходными
параметрами. Для передачи входного параметра используется
метод setXXX, унаследованный от PreparedStatement.


Slide 30

Callable Statement. OUT и IN-OUT параметры
Регистрация выходных параметров осуществляется следующим
образом
CallableStatement cs = conn.prepareCall ("begin ? := foo(?); end;");
cs.registerOutParameter(1,Types.CHAR);
cs.setString(2, "aa");
cs.executeUpdate();
String result = cs.getString(1);


Для параметра IN-OUT необходимо определить его сначала методом
setXXX, а затем registerOutParameter.
CallableStatement cstmt = con.prepareCall( "{call reviseTotal(?)}");
cstmt.setByte(1, 25); cstmt.registerOutParameter(1,
java.sql.Types.TINYINT);
cstmt.executeUpdate();
byte x = cstmt.getByte(1);


Slide 31

Result Set – набор данных






ResultSet содержит все строки, удовлетворяющие
условиям в SQL-выражении и предоставляет
доступ к данным в этих строках посредством
набора get-методов, которые организуют доступ к
колонкам текущей строки.
Метод ResultSet.next используется для
перемещения к следующей строке ResultSet,
делая ее текущей.
Набор данных результата является таблицей с
заголовками колонок и соответствующих
значений, возвращенных запросом.
Column1

Column2

Column3

135

Moscow

11.12.2008

173

Kemerovo

11.12.2008


Slide 32

Result Set – набор данных
Выполнение SQL-запроса, который возвращает коллекцию
строк, в которой колонка 1 - это int, колонка 2 - String и
колонка 3 - Float
java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");

while (r.next()) { // Напечатать значения в текущей строке.
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}


Slide 33

Result Set. Доступ к колонкам






ResultSet содержит т.н. курсор, который указывает на
текущую строку данных. Каждый раз, когда выполняется
метод next, курсор перемещается на одну строку вниз.
Изначально курсор спозиционирован перед первой строкой, и
первый вызов next премещает его на первую строку.
Методы getXXX предоставляют доступ к значениям в
колонках в текущей строке. В пределах одной строки
значения могут быть считаны в любом порядке, но ради
обеспечения большей совместимости рекомендуется
считывать их подряд слева направо и делать это только один
раз.
Для указания колонки можно использовать либо ее имя, либо
ее номер. Например, если вторая колонка объекта ResultSet
rs называется "title" и хранит строковое значение, то извлечь
его можно одним из двух способов:



String s = rs.getString("title");
String s = rs.getString(2);


Slide 34

Result Set. Доступ к колонкам
Вариант с использование имен колонок существует для
того, чтобы пользователь задавал методам getXXX те
же имена колонок, что он использует в запросе.
 Если выражение select не указывает имена колонок
(например "select * from table1" или в случаях, когда
колонка вычисляется) должны использоваться номера
колонок.
 В некторых случаях имена двух колонок могут
совпадать. Тогда при использовании имен колонок в
методах getXXX возвращается значение первой
подходящей колонки. Таким образом, чтобы считать
значение других колонок с таким же именем, надо
использовать индексы колонок. Кроме того,
использование индексов немного эффективнее.



Slide 35

Result Set. Значение NULL в результатах



Метод wasNull() проверяет, равно ли Null последнее
считанное из колонки значение.
Если значение равно Null, то метод getXXX() возвращает:
 null для тех из методов getXXX, которые возвращают
объекты (getString, getBytes, getDate…)
 нулевое значение для getByte, getShort, getInt, getLong,
getFloat, and getDouble.
 false в случае getBoolean.
while(results.next()) {
id = results.getInt(1);
lastname = results.getString(2);
email = results.getString(3);
if(results.wasNull()) { // почему wasNull от results?
email = "no email";}


Slide 36

Обработка исключений SQL




Для перехвата исключений SQL существует класс
(с производными от него) java.sql.SQLException.
Исключения могут возникать как в самой СУБД, так
и в JDBC.
Стандартная обработка исключения включает в
себя:







получение текста ошибки (getMessage())
получение кода ошибки (getErrorCode())
получение состояния SQL (getSQLState())
распечатку стека вызова (printStackTrace()).

Метод getMessage() возвращает сообщение
ошибки. Если сообщение содержит префикс ORA,
то исключение произошло в СУБД, иначе в JDBC.


Slide 37

Обработка исключений SQL



getErrorCode() – возвращает пятизначный код
ошибки как для ошибок СУБД, так и JDBC
getSQLState() - возвращает пятизначный код
ошибки, отображающий состояние SQL. Если
ошибка возникла в JDBC, то код не содержит
никакой полезной информации
catch(SQLException e);
{System.out.println("exception: " + e.getMessage());}



printStackTrace() – выводит стек вызовов функций,
приводящих к ошибке.
try { }
catch(SQLException e) { e.printStackTrace (); }


Slide 38





















import java.sql.*;
import oracle.jdbc.driver.*;
class JDBCVersion
{
public static void main (String args[])
throws SQLException
{
// Load the Oracle JDBC driver
DriverManager.registerDriver
(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection
("jdbc:oracle:thin:@host:port:sid","scott","tiger");
// Create Oracle DatabaseMetaData object
DatabaseMetaData meta = conn.getMetaData();
// gets driver info:
System.out.println("JDBC driver version is " + meta.getDriverVersion());
}
}


Slide 39



Благодарю за внимание!



Вопросы?