0.98M
Category: databasedatabase

Объектно-ориентированное программирование в Oracle PL/SQL

1.

<Insert Picture Here>
Объектно-ориентированное
программирование в Oracle PL/SQL
Игорь Мельников
Старший консультант по базам данных

2.

План
Реализация ООП в Oracle PL/SQL
Рефлексия типов в PL/SQL
Паттерны проектирования в PL/SQL
СУБД Oracle Database как фабрика и
репозитарий объектов
• Пример реализации универсальной
библиотеки типов PL/SQL
2
<Insert Picture Here>

3.

Реализация парадигм ООП в PL/SQL
3

4.

Парадигмы ООП в PL/SQL
Реализация в PL/SQL
Инкапсуляция
Наследование
Полиморфизм
Ограничения в реализации
Дополнительные возможности
4
Приведение типов
Перегрузка операторов сравнения
Коллекции объектов
Хранение объектов в СУБД
Ссылки на объекты (OBJECT REF)
<Insert Picture Here>

5.

Инкапсуляция
Атрибуты типа
Объектный тип PL/SQL - спецификация
CREATE
CREATE OR
OR REPLACE
REPLACE TYPE
TYPE TAccount
TAccount AS
AS OBJECT
OBJECT
((
FNumber
FNumber VARCHAR2(20),
VARCHAR2(20),
Конструктор типа
FCustomer
TCustomer,
FCustomer TCustomer,
Метод экземпляра
CONSTRUCTOR
in
CONSTRUCTOR FUNCTION
FUNCTION TAccount(pAcNo
TAccount(pAcNo
in varchar2)
varchar2)
RETURN
RETURN SELF
SELF AS
AS RESULT,
RESULT,
MEMBER
MEMBER
FUNCTION
FUNCTION getAmount
getAmount RETURN
RETURN NUMBER,
NUMBER,
STATIC
STATIC
PROCEDURE
PROCEDURE exportAllAccounts
exportAllAccounts
))
NOT
NOT FINAL;
FINAL;
5
Статический метод

6.

Инкапсуляция
Объектный тип PL/SQL – реализация (тело)
CREATE
CREATE OR
OR REPLACE
REPLACE TYPE
TYPE BODY
BODY TAccount
TAccount IS
IS
CONSTRUCTOR
CONSTRUCTOR FUNCTION
FUNCTION TAccount(pAccNo
TAccount(pAccNo in
in varchar2)
varchar2) RETURN
RETURN SELF
SELF AS
AS
RESULT
IS
RESULT IS
BEGIN
BEGIN
self.FNumber
self.FNumber :=
:= pAccNo;
pAccNo;
self.load;
self.load;
RETURN;
RETURN;
END;
END;
MEMBER
FUNCTION
MEMBER
FUNCTION getAmount
getAmount RETURN
RETURN NUMBER
NUMBER IS
IS
xResult
xResult NUMBER(20,2);
NUMBER(20,2);
BEGIN
BEGIN

……
……
……
……

return
return v_xResult;
v_xResult;
END;
END;
END;
END;
6

7.

Переменные объектного типа
Использование
DECLARE
DECLARE
xCreditAcc
xCreditAcc TAccount;
TAccount;
xDebetAcc
xDebetAcc TAccount;
TAccount;
xTransaction
xTransaction TTransaction;
TTransaction;
BEGIN
BEGIN
xCreditAcc
xCreditAcc :=
:= new
new TAccount(
TAccount('40101810400000010801'
'40101810400000010801');
);
xDebetAcc
xDebetAcc :=
:= new
new TAccount(
TAccount('40101810400000020304'
'40101810400000020304');
);
xTransaction
xTransaction :=
:= new
new TTransaction(xDebetAcc,
TTransaction(xDebetAcc,
xCreditAcc,
xCreditAcc,
100);
100);
xTransaction.doIt;
xTransaction.doIt;
COMMIT;
COMMIT;
END;
END;
7

8.

Наследование
Наследование типов PL/SQL - спецификация
CREATE
CREATE OR
OR REPLACE
REPLACE TYPE
TYPE TAccount
TAccount UNDER
UNDER TPersistent
TPersistent
((
FNumber
FNumber VARCHAR2(20),
VARCHAR2(20),
FCustomer
FCustomer TCustomer,
TCustomer,
Тип - предок
CONSTRUCTOR
CONSTRUCTOR FUNCTION
FUNCTION TAccount
TAccount RETURN
RETURN SELF
SELF AS
AS RESULT,
RESULT,
MEMBER
MEMBER
FUNCTION
FUNCTION getAmount
getAmount RETURN
RETURN NUMBER,
NUMBER,
STATIC
STATIC
PROCEDURE
PROCEDURE exportAllAccounts
exportAllAccounts
))
NOT
NOT FINAL;
FINAL;
8

9.

Наследование
Пример: визуальное представление
• Перегрузка метода
сохранения объекта
(save)
TObject
save
TPersistent
Абстрактный метод
save
TAccount
Перегруженный метод
9

10.

Полиморфизм
Перегрузка методов в типе-потомке PL/SQL
CREATE
CREATE OR
OR REPLACE
REPLACE TYPE
TYPE TAccount
TAccount UNDER
UNDER TPersistent
TPersistent
((
FNumber
FNumber VARCHAR2(20),
VARCHAR2(20),
FCustomer
FCustomer TCustomer,
TCustomer,
OVERRIDING
OVERRIDING MEMBER
MEMBER PROCEDURE
PROCEDURE save,
save,
OVERRIDING
OVERRIDING MEMBER
MEMBER PROCEDURE
PROCEDURE remove,
remove,
STATIC
STATIC
))
NOT
NOT FINAL;
FINAL;
10
FUNCTION
FUNCTION load(v_pId
load(v_pId IN
IN NUMBER)
NUMBER) RETURN
RETURN
TAccount
TAccount
Не терминальный тип
в иерархии !

11.

Полиморфизм
Вызов унаследованного метода в типе-потомке
CREATE
CREATE OR
OR REPLACE
REPLACE TYPE
TYPE BODY
BODY TAccount
TAccount IS
IS
OVERRIDING
OVERRIDING MEMBER
MEMBER PROCEDURE
PROCEDURE save
save IS
IS
BEGIN
BEGIN
(SELF
(SELF AS
AS TPersistent).save;
TPersistent).save;
INSERT
INSERT INTO
INTO Accounts
Accounts …


……
… …
… …
… …

END;
END;

… …
… …
… …
… …

END;
END;
11

12.

Ограничения в ООП PL/SQL
• Нет разграничения видимости членов типов
(все PUBLIC!)
• Не поддерживаются свойства (property)
• Нет атрибутов типа (static members) – можно
эмулировать через статический метод и пакет
STATIC
STATIC FUNCTION
FUNCTION getRootDict
getRootDict RETURN
RETURN TDictionary
TDictionary IS
IS
BEGIN
BEGIN
RETURN
RETURN dict_service.getRootDict;
dict_service.getRootDict;
END;
END;
12

13.

Дополнительные возможности
Приведение типов - oператор TREAT
DECLARE
DECLARE
v_xObj
v_xObj TCustomer;
TCustomer;
BEGIN
BEGIN
v_xObj
v_xObj :=
:= TREAT(TObjectFactory.Load(123)
TREAT(TObjectFactory.Load(123) AS
AS TCustomer);
TCustomer);
END;
END;
13

14.

Дополнительные возможности
Перегрузка операторов сравнения
• Необходимо реализовать метод сравнения
ORDER
/**
/**
** @param
@param pObject
pObject -- объект
объект сс которым
которым происходит
происходит сравнение
сравнение
** @return
@return 0,
0, -- если
если объекты
объекты равны,<br>
равны,<br> 11 -- если
если текущий
текущий
объект
объект больше,
больше, чем
чем pObject<br>,
pObject<br>, -1
-1 -- если
если текущий
текущий объект
объект
меньше,
меньше, чем
чем pObject
pObject
*/
*/
ORDER
ORDER MEMBER
MEMBER FUNCTION
FUNCTION compare(pObject
compare(pObject in
in
TObject)
RETURN
TObject)
RETURN pls_integer
pls_integer
• Метод ORDER неявно вызывается вместо
операций: <, <=, >=, =, >
14

15.

Дополнительные возможности
Коллекции объектов
• Создаются на уровне СУБД:
CREATE
CREATE TYPE
TYPE TTableOfString
TTableOfString AS
AS TABLE
TABLE OF
OF VARCHAR2(128);
VARCHAR2(128);
CREATE
CREATE TYPE
TYPE TTableOfAccount
TTableOfAccount AS
AS TABLE
TABLE OF
OF TAccount;
TAccount;
• Имеют встроенные методы:
15
Неявный конструктор
COUNT
DELETE
EXTEND
TRIM

16.

Дополнительные возможности
Операторы для коллекций объектов
16
<>, = - проверяет две коллекции на (не) равенство;
SET – удаляет дубликаты из коллекции;
[NOT] MEMBER – проверка вхождения элемента;
MULTISET INTERSECT – пересечение коллекций;
MULTISET UNION – объединение коллекций;
MULTISET EXCEPT – из одной вычесть другую;
IS A [NOT] SET – содержит уникальные элементы;
NOT SUBMULTISET OF – проверка на подмножество;

17.

Дополнительные возможности
Коллекции объектов - использование
Для использования операторов с коллекциями,
объектный тип должен иметь метод ORDER – для
сравнения объектов
DECLARE
DECLARE
xAccArray
xAccArray TAccountArray;
TAccountArray;
xAcc
TAccount
xAcc
TAccount :=
:= new
new TAccount('101');
TAccount('101');
BEGIN
BEGIN
xAccArray
xAccArray :=
:= new
new TAccountArray(new
TAccountArray(new TAccount('101'),
TAccount('101'),
new
new TAccount('102'));
TAccount('102'));
IF
IF xAcc
xAcc MEMBER
MEMBER xAccTArray
xAccTArray THEN
THEN
println('Is
println('Is member!');
member!');
END
END IF;
IF;
END;
END;
17

18.

Хранение объектов в БД
Объектные таблицы
Объектные таблицы
CREATE
CREATE TABLE
TABLE Accounts
Accounts OF
OF TAccount;
TAccount;
Колонка реляционной таблицы - объект
CREATE
CREATE TABLE
TABLE Users
Users
((
Id
NUMBER(6),
Id
NUMBER(6),
Properties
Properties TObjectProperties
TObjectProperties
);
);
18

19.

Ссылки на объекты
Object REF
Ссылка на хранимый объект в БД
CREATE
CREATE TYPE
TYPE TTransaction
TTransaction AS
AS OBJECT
OBJECT
((
DebetAcc
DebetAcc REF
REF TAccount,
TAccount,
CreditAcc
CreditAcc REF
REF TAccount,
TAccount,
Amount
Amount NUMBER
NUMBER
);
);
100.00
To debet account
object
19
To credit account object

20.

Ссылки на объекты
Дополнительные возможности
• Дополнительный пакет UTL_REF
DELETE_OBJECT
LOCK_OBJECT
SELECT_OBJECT
UPDATE_OBJECT
• Эмуляция REF через объектные представления:
CREATE
CREATE VIEW
VIEW v$AccountsRef
v$AccountsRef OF
OF TAccount
TAccount
WITH
WITH OBJECT
OBJECT IDENTIFIER(Id)
IDENTIFIER(Id)
SELECT
SELECT
a.Id
AS
a.Id
AS OID,
OID,
a.FNumber
a.FNumber
FROM
FROM
accounts
accounts a;
a;
20

21.

Рефлексия объектных типов в
PL/SQL
21

22.

Generic PL/SQL types
Обобщенные типы
• ANYTYPE – получение информации о типе, а также
создание анонимных типов
• ANYDATA – представляет собой экземпляр любого
типа
• ANYDATASET - представляет собой множество
экземпляров какого-либо типа (generic recordset)
• DBMS_TYPES – пакет (package) предоставляет набор
констант и исключений для работы с обобщенными
типами
22

23.

Тип ANYTYPE
Работа с уже существующими типами в БД
STATIC
STATIC FUNCTION
FUNCTION GETPERSISTENT(
GETPERSISTENT(
schema_name
schema_name IN
IN VARCHAR2,
VARCHAR2,
type_name
IN
type_name
IN VARCHAR2,
VARCHAR2,
version
IN
version
IN VARCHAR2
VARCHAR2 DEFAULT
DEFAULT NULL)
NULL)
RETURN
RETURN ANYTYPE;
ANYTYPE;
• Статическая функция GETPERSISTENT – создание экземпляра
ANYTYPE по уже существующему в БД типу
DECLARE
DECLARE
В том числе и по
v_xType
ANYTYPE;
v_xType ANYTYPE;
примитивным типам!
BEGIN
BEGIN
v_xType
v_xType :=
:= ANYTYPE.getPersistent(‘MY_SCHEMA‘,‘TACCOUNT‘);
ANYTYPE.getPersistent(‘MY_SCHEMA‘,‘TACCOUNT‘);
END;
END;
23

24.

Тип ANYTYPE
Получение информации об атрибуте
MEMBER
IN
MEMBER FUNCTION
FUNCTION GETATTRELEMINFO(pos
GETATTRELEMINFO(pos
IN PLS_INTEGER,
PLS_INTEGER,
prec
OUT
prec
OUT PLS_INTEGER,
PLS_INTEGER,
scale
OUT
scale
OUT PLS_INTEGER,
PLS_INTEGER,
Экземпляр ANYTYPE,
Длина
Порядковый
(для
текстовых
если
атрибут
–номер
это
len
OUT
len
OUT PLS_INTEGER,
PLS_INTEGER,
атрибута
атрибутов)
в
типе
объект!точность
Возвращает
csid
OUT
csid
OUT PLS_INTEGER,
PLS_INTEGER,
Character
set
Id
(для числовых
Возвращает
масштаб
csfrm
OUT
csfrm
OUT PLS_INTEGER,
PLS_INTEGER,
(для
символьных
Character
set
form
атрибутов)
(для
числовых
атрибутов)
attr_elt_type
(для
символьных
attr_elt_type OUT
OUT ANYTYPE,
ANYTYPE,
атрибутов)
атрибутов)
aname
OUT
aname
OUT VARCHAR2)
VARCHAR2)
Имя атрибута
RETURN
RETURN PLS_INTEGER;
PLS_INTEGER;
• Возвращает код типа элемента (определены в пакете
DBMS_TYPES)
24

25.

Тип ANYTYPE
Создание анонимного типа
SQL>
SQL> DECLARE
DECLARE
22
xType
xType AnyType;
AnyType;
33 BEGIN
BEGIN
44 AnyType.BeginCreate(DBMS_TYPES.TYPECODE_OBJECT,
AnyType.BeginCreate(DBMS_TYPES.TYPECODE_OBJECT,
55
xType);
xType);
66 xType.addAttr(aname
xType.addAttr(aname =>
=> 'AccountNumber',
'AccountNumber',
77
typecode
typecode =>
=> DBMS_TYPES.TYPECODE_VARCHAR2,
DBMS_TYPES.TYPECODE_VARCHAR2,
88
prec
prec =>
=> 0,
0,
99
scale
scale =>
=> 0,
0,
10
len
=>
10
len
=> 0,
0,
11
csid
11
csid =>
=> 0,
0,
12
csfrm
12
csfrm =>
=> 0);
0);
13
xType.EndCreate;
13
xType.EndCreate;
14
14 END;
END;
25

26.

Тип ANYDATA
Получение информации об экземпляре типа
• BEGINCREATE – начало создания нового экземпляра AnyData
• ENDCREATE – завершение создания экземпляра AnyData
• PIECEWISE
– установка режима создания экземпляра для не
примитивных объектов
• SET*
– установить значение атрибута
• GET*
– получение значения атрибута
• GETTYPENAME– получить имя типа (для типов уже существующих
в БД)
• GETTYPE
– получение экземпляра ANYTYPE описывающего
тип объекта
• CONVERTOBJECT – получение экземпляра ANYDATA из любого
объекта
26

27.

Два способа создания экз. ANYDATA
1-ый: с помощью вызова методов CONVERT
SQL>
SQL> DECLARE
DECLARE
22
xType
ANYTYPE;
xType
ANYTYPE;
33
xAccount
xAccount TAccount
TAccount :=
:= new
new TAccount(‘123‘);
TAccount(‘123‘);
44
xVar
ANYDATA;
xVar
ANYDATA;
55 BEGIN
BEGIN
66
xVar
xVar :=
:= ANYDATA.ConvertObject(xAccount);
ANYDATA.ConvertObject(xAccount);
77 DBMS_OUTPUT.PUT_LINE(xVar.getType(xType));
DBMS_OUTPUT.PUT_LINE(xVar.getType(xType));
88 DBMS_OUTPUT.PUT_LINE(xVar.getTypeName);
DBMS_OUTPUT.PUT_LINE(xVar.getTypeName);
99 END;
END;
10
10 //
108
108
ABC.TACCOUNT
ABC.TACCOUNT
27

28.

Два способа создания экз. ANYDATA
2-ой: вызов методов BeginCreate(), Set*(), EndCreate
SQL>
SQL> DECLARE
DECLARE
22 xObject
xObject AnyData;
AnyData;
33 xType
xType AnyType
AnyType :=
:= TAccount.getAnyType;
TAccount.getAnyType;
44 xAcc
xAcc TAccount;
TAccount;
Наполнение объекта
55 BEGIN
BEGIN
по атрибутам, а не
66 AnyData.BeginCreate(xType,xObject);
AnyData.BeginCreate(xType,xObject);
сразу!
77 xObject.PieceWise();
xObject.PieceWise();
88 xObject.setVarchar2('MyAccNumber');
xObject.setVarchar2('MyAccNumber'); xObject.setNumber(100);
xObject.setNumber(100);
99 xObject.EndCreate;
xObject.EndCreate;
10
10
11
11 IF
IF xObject.getObject(xAcc)
xObject.getObject(xAcc) == DBMS_TYPES.SUCCESS
DBMS_TYPES.SUCCESS THEN
THEN
12
dbms_output.put_line(xAcc.getString());
12
dbms_output.put_line(xAcc.getString());
13
13 END
END IF;
IF;
14
14 END;
END;
15
15 //
AccountNo
AccountNo =>
=> MyAccNumber
MyAccNumber || Amount
Amount =>
=> 100
100
28

29.

Тип ANYDATASET
Обобщенные выборки
• Основное использование – реализация обобщенных
табличных функций,структура курсора которых
неизвестна на этапе компиляции
CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION
getReport(pType
getReport(pType in
in number)
number) RETURN
RETURN AnyDataSet
AnyDataSet
PIPELINED
PIPELINED USING
USING TReportRowSet;
TReportRowSet;
• Тело табличной функции отсутствует!
• Его заменяет тип TReportRowSet – реализует
интерфейс ODCITable
29

30.

Тип ANYDATASET
Интерфейс ODCITable – информация для SQL-Engine
30
ODCITableDescribe – возвращает структуру курсора
ODCITableStart – открытие курсора
ODCITableFetch – извлечение записи
ODCITableClose – закрытие курсора
ODCIPrepare – получение контекста выполнения
курсора

31.

Интерфейс ODCITable
Пример
create
create or
or replace
replace type
type TReportRowSet
TReportRowSet as
as object
object ((
constructor
constructor function
function TReportRowSet(v_pType
TReportRowSet(v_pType in
in varchar2
varchar2 :=
:= null)
null) return
return self
self as
as
result,
result,
static
static function
function ODCITableStart(sctx
ODCITableStart(sctx in
in out
out nocopy
nocopy TReportRowSet,
TReportRowSet,
v_pType
v_pType in
in varchar2
varchar2 :=
:= null)
null) return
return number,
number,
member
member function
function ODCITableFetch(self
ODCITableFetch(self in
in out
out nocopy
nocopy TReportRowSet,
TReportRowSet,
nrows
nrows in
in number,
number,
rws
return
rws out
out AnyDataSet)
AnyDataSet)
return number,
number,
static
static function
function ODCITablePrepare(sctx
ODCITablePrepare(sctx out
out nocopy
nocopy TReportRowSet,
TReportRowSet,
tf_info
tf_info in
in Sys.ODCITabFuncInfo,
Sys.ODCITabFuncInfo,
v_pType
v_pType in
in varchar2
varchar2 :=
:= null)
null) return
return number,
number,
member
return
member function
function ODCITableClose(self
ODCITableClose(self in
in TReportRowSet)
TReportRowSet)
return number,
number,
static
static function
function ODCITableDescribe(rtype
ODCITableDescribe(rtype out
out AnyType,
AnyType,
v_pType
v_pType in
in varchar2
varchar2 :=
:= null)
null) return
return number,
number,
static
return
static function
function getRecordType(v_pType
getRecordType(v_pType in
in varchar2
varchar2 :=
:= null)
null)
return AnyType
AnyType
31
http://www.oracle.com/global/ru/oramag/nov2004/gen_dev_10g.html

32.

Паттерны проектирования в PL/SQL
32

33.

Шаблон “Одиночка” (Singleton)
Должен быть только один экземпляр типа
CREATE
CREATE TYPE
TYPE BODY
BODY TSingleton
TSingleton IS
IS
STATIC
STATIC FUNCTION
FUNCTION getInstance
getInstance RETURN
RETURN
TSingleton
TSingleton IS
IS
BEGIN
BEGIN
RETURN
RETURN singleton_service.getInstance;
singleton_service.getInstance;
END;
END;
Экземпляр хранится
в глобальной
переменной пакета !
33

34.

Шаблон “Наблюдатель” (Observer)
Шаблон “Наблюдатель”
34

35.

Шаблон “Наблюдатель” (Observer)
Реализация в PL/SQL (спецификация)
CREATE
CREATE TYPE
TYPE TArrayOfObserver
TArrayOfObserver AS
AS TABLE
TABLE OF
OF TObserver;
TObserver;
CREATE
CREATE TYPE
TYPE TSubject
TSubject AS
AS OBJECT
OBJECT
((
FObservers
FObservers TArrayOfObserver,
TArrayOfObserver,
MEMBER
MEMBER PROCEDURE
PROCEDURE attach(pObserver
attach(pObserver IN
IN OUT
OUT NOCOPY
NOCOPY TObserver),
TObserver),
MEMBER
MEMBER PROCEDURE
PROCEDURE detach(pObserver
detach(pObserver IN
IN OUT
OUT NOCOPY
NOCOPY TObserver),
TObserver),
MEMBER
MEMBER PROCEDURE
PROCEDURE notify,
notify,

……
……

););
35

36.

Шаблон “Наблюдатель” (Observer)
Реализация в PL/SQL (тело)
CREATE
CREATE TYPE
TYPE BODY
BODY TSubject
TSubject IS
IS
MEMBER
MEMBER PROCEDURE
PROCEDURE attach(pObserver
attach(pObserver IN
IN OUT
OUT NOCOPY
NOCOPY TObserver)
TObserver) IS
IS
BEGIN
BEGIN
FObservers.extend(1);
FObservers.extend(1);
FObservers(FObservers.count)
FObservers(FObservers.count) :=
:= pObserver;
pObserver;
END;
END;
MEMBER
MEMBER PROCEDURE
PROCEDURE detach(pObserver
detach(pObserver IN
IN OUT
OUT NOCOPY
NOCOPY TObserver)
TObserver) IS
IS
BEGIN
BEGIN
IF
IF pObserver
pObserver MEMBER
MEMBER FObservers
FObservers THEN
THEN
FObservers.DELETE(findObserver(pObserver));
FObservers.DELETE(findObserver(pObserver));
END
END IF;
IF;
END;
END;
36

37.

Шаблон “Наблюдатель” (Observer)
Реализация в PL/SQL (тело - продолжение)
MEMBER
MEMBER PROCEDURE
PROCEDURE notify
notify IS
IS
xCount
xCount SIMPLE_INTEGER
SIMPLE_INTEGER :=
:= FObservers.count;
FObservers.count;
BEGIN
BEGIN
FOR
FOR xIndex
xIndex IN
IN 1..xCount
1..xCount
LOOP
LOOP
FObservers(xIndex).Update;
FObservers(xIndex).Update;
END
END LOOP;
LOOP;
END;
END;
37

38.

Шаблон “Фабричный метод”
Factory Method
CREATE
CREATE TYPE
TYPE TObjectFactory
TObjectFactory AS
AS OBJECT
OBJECT
((
STATIC
STATIC FUNCTION
FUNCTION createObject(pTypeName
createObject(pTypeName VARCHAR2)
VARCHAR2) RETURN
RETURN TObject
TObject

……
……

););
38
http://ru.wikipedia.org/

39.

СУБД Oracle Database как фабрика и
репозитарий объектов
39

40.

Недостатки хранения объектов
Хранение в объектных таблицах Oracle
• Крайне затруднена модификация исх. кода объектов
(есть связь с таблицей!)
• Сложный синтаксис обращения к объектной таблице
• Изменение атрибутов объекта ведет к тяжелой
процедуре модификации структуры объектной таблицы
40

41.

Хранение объектов в реляц. таблицах
Совмещение преимуществ ООП и реляционного
подхода
• Хранить Persistent-объекты в обычных реляционных таблицах
• Доступ реализовать в виде обычного реляционного SQL, в
коде методов объектного типа
• Когда необходимо, применять обычный реляционный доступ к
таблицам
41

42.

Репозитарий объектов в СУБД Oracle
42

43.

Репозитарий объектов в Oracle
Базовая иерархия классов
43

44.

Работа с репозитарием
Тип TPersistentObject
CREATE
CREATE TYPE
TYPE BODY
BODY TPersistentObject
TPersistentObject IS
IS
MEMBER
MEMBER PROCEDURE
PROCEDURE save
save IS
IS
BEGIN
BEGIN
TObjectFactory.register(self);
TObjectFactory.register(self);
END;
END;
MEMBER
MEMBER PROCEDURE
PROCEDURE remove
remove IS
IS
BEGIN
BEGIN
TObjectFactory.unregister(self);
TObjectFactory.unregister(self);
END;
END;
...
... ...
... ...
...
44

45.

Работа с объектами в приложении
Пример: MS Visual Studio .NET
• Необходима поддержка объектов в средствах
разработки приложений!
• Oracle Developer Tools for VS .Net
• UDT Custom Class Code Generation Wizard
• Генерирует класс на C#,VB.NET,C++ совпадающий по сигнатуре
с типом PL/SQL
• Отображение типов PL/SQL в классы .NET
• Клиент прозрачно использует объекты в терминах своего
окружения !!!
45

46.

Oracle Developer Tools for VS .NET
UDT Custom Class Code Generation Wizard
46

47.

Custom Class Code Generation Wizard
Прозрачное использование объекта в приложении
47

48.

Пример реализации универсальной
библиотеки типов PL/SQL
48

49.

Постановка задачи
Необходимость в библиотеке
• Поддержки репозитария объектов недостаточно !
• Часто приходится повторять один и тот же код:
Работа с списками
Работа с хеш-таблицами
Обработка массива строк
Обработка исключений
И т.д.
• Необходима библиотека универсальных (проблемнонезависимых) типов – по аналогии с JDK, .NET, VCL и
т.д.
49

50.

PCL 2.0
PL/SQL Class Library – набор типов PL/SQL
TObject
THashTable
TQueue
EException
TPersistentObject
-Count : Integer
-Id : Decimal
+getKeys : TArrayString()
+remove(in pKey : String)
+clear()
+save()
+remove()
THashTableObject
50
TList
THashTableString
THashTableNumber
THashTableDate

51.

Работа с списками строк в PCL
Тип TListString
DECLARE
DECLARE
v_xList
TListString
v_xList
TListString :=
:= new
new TListString();
TListString();
v_xLineList
v_xLineList TListString
TListString :=
:= new
new TListString();
TListString();
BEGIN
BEGIN
v_xLineList.setDelimiter(';');
v_xLineList.setDelimiter(';');
v_xList.loadFromFile(v_cDataDir,v_cFileName);
v_xList.loadFromFile(v_cDataDir,v_cFileName);
v_xRowCount
v_xRowCount :=
:= v_xList.getCount;
v_xList.getCount;
FOR
FOR v_xIndex
v_xIndex IN
IN 1..v_xRowCount
1..v_xRowCount
LOOP
LOOP
:v_xCurrLine
:v_xCurrLine :=
:= v_xList.getItem(v_xIndex);
v_xList.getItem(v_xIndex);
v_xLineList.setCommaText(v_xCurrLine);
v_xLineList.setCommaText(v_xCurrLine);
:v_xCompanyName
:v_xCompanyName :=
:= v_xLineList.getItem(1);
v_xLineList.getItem(1);
.... .... …

51

52.

Обработка исключений
Пример: использование типов-исключений
BEGIN
BEGIN
throw(new
throw(new EFileNotFoundException('config.ini'));
EFileNotFoundException('config.ini'));
EXCEPTION
EXCEPTION
WHEN
WHEN exception_service.EFileNotFound
exception_service.EFileNotFound THEN
THEN
exception_service.printStack;
exception_service.printStack;
END;
END;
//
Регистрация объекта
исключения в стеке
ошибок PCL
52

53.

Инкапсуляция функций API в типы PCL
Пример: инкапсуляция Oracle AQ в тип PL/SQL
CREATE
CREATE TYPE
TYPE TQueueObjectAQ
TQueueObjectAQ UNDER
UNDER TQueueObject
TQueueObject ((
FTableName
FTableName varchar2(64),
varchar2(64),
FTypeName
FTypeName varchar2(64),
varchar2(64),
OVERRIDING
return
OVERRIDING MEMBER
MEMBER FUNCTION
FUNCTION peek
peek
return TObject,
TObject,
OVERRIDING
OVERRIDING MEMBER
MEMBER FUNCTION
FUNCTION dequeue
dequeue return
return TObject,
TObject,
OVERRIDING
OVERRIDING MEMBER
MEMBER PROCEURE
PROCEURE enqueue(pObject
enqueue(pObject TObject),
TObject),
MEMBER
MEMBER PROCEURE
PROCEURE startQueue,
startQueue,
MEMBER
MEMBER PROCEURE
PROCEURE stopQueue
stopQueue

……
… …

• Вместо использования громоздкого и сложного API – набор
понятных и коротких типов
• Сокращается исходный код и повышается его читабельность
53

54.

Работа с объектной моделью MS Excel
Инкапсуляция COM Automation Feature в PL/SQL
DECLARE
DECLARE
v_xAppExcel
v_xAppExcel TExcelApplication
TExcelApplication :=
:= new
new TExcelApplication();
TExcelApplication();
v_xWorkBooks
v_xWorkBooks TWorkbooks;
TWorkbooks;
v_xWorkBook
v_xWorkBook TWorkbook;
TWorkbook;
v_xWorkSheets
v_xWorkSheets TWorkSheets;
TWorkSheets;
v_xWorkSheet
v_xWorkSheet TWorkSheet;
TWorkSheet;
v_xCell
TCell;
v_xCell
TCell;
BEGIN
BEGIN
v_xWorkBooks
v_xWorkBooks :=
:= v_xAppExcel.WorkBooks;
v_xAppExcel.WorkBooks;
v_xWorkBook
v_xWorkBook :=
:= v_xWorkBooks.Open('c:\temp\test.xls');
v_xWorkBooks.Open('c:\temp\test.xls');
v_xWorkSheets
v_xWorkSheets :=
:= v_xWorkBook.WorkSheets;
v_xWorkBook.WorkSheets;
v_xWorkSheet
v_xWorkSheet :=
:= v_xWorkSheets.Item('test');
v_xWorkSheets.Item('test');
v_xCell
:=
v_xCell
:= v_xWorkSheet.getCell(2,1);
v_xWorkSheet.getCell(2,1);
dbms_output.put_line(v_xCell.getValue);
dbms_output.put_line(v_xCell.getValue);
END;
END;
54

55.

PL/SQL Class Library
Резюме
• Объектно-ориентированная библиотека типов PL/SQL общего
назначения
• Инкапсулирует часто используемый функционал:
• Стеки, списки, очереди, хэш-таблицы, нити (thread), потоки (stream) и т.д.
• Работа с ОС: файлы, каталоги, запись/чтение файлов сервера
• Часть функций API Oracle (built-in packages) – AQ, LOB, JOB
• Также реализует поддержку репозитария persistent-объектов и
работу с ними
Подсистема ведения справочников
Подсистема групп объектов
Logging (подсистема ведения журналов) – аналог log4j
Подсистема обработки обновлений (patching)
• Объем: ~ 150 типов и ~50 тыс. строк кода PL/SQL
55

56.

PL/SQL Class Library
Пример внедрения (success story ☺ )
• Заказная разработка: “Система ведения контактной информации”
Учет компаний-партнеров и их атрибутов
Учет договоров
Учет контактов компаний-партнеров
Учет компаний-заказчиков
Учет контактов компаний-заказчиков
• Используемое окружение
Oracle Database EE 11.1.0.6.3
Oracle Partitioning Option
Oracle Advanced Compression Option
Oracle Application Express 3.1.1 + AJAX
• Объем: ~ 70 таблиц, ~200 типов и ~70 тыс. строк кода PL/SQL
56

57.

PL/SQL Class Library
57

58.

Использование PL/SQL-типов в APEX
58

59.

ООП PL/SQL
Заключение
• Поддерживает все основные парадигмы ООП
• Позволяет создавать прикладное ПО в ООстиле и получить все преимущества ООПподхода
• Наличие библиотеки PL/SQL-типов позволяет
достичь повторного использования кода,
уменьшить сложность проектов и сократить
время разработки
59

60.

60

61.

<Insert Picture Here>
Игорь Мельников
Старший консультант Oracle СНГ
Email: [email protected]
Phone: +7 (495) 641 14 00
Direct:
+7 (495) 641 14 42
Mobile: +7 (915) 205 26 27

62.

62
English     Русский Rules