Объектно-ориентированное программирование в Oracle PL/SQL
Transcription
Объектно-ориентированное программирование в Oracle PL/SQL
<Insert Picture Here> Объектно-ориентированное программирование в Oracle PL/SQL Игорь Мельников Старший консультант по базам данных План • • • • Реализация ООП в Oracle PL/SQL Рефлексия типов в PL/SQL Паттерны проектирования в PL/SQL СУБД Oracle Database как фабрика и репозитарий объектов • Пример реализации универсальной библиотеки типов PL/SQL 2 <Insert Picture Here> Реализация парадигм ООП в PL/SQL 3 Парадигмы ООП в PL/SQL Реализация в PL/SQL • • • • • Инкапсуляция Наследование Полиморфизм Ограничения в реализации Дополнительные возможности • • • • • 4 Приведение типов Перегрузка операторов сравнения Коллекции объектов Хранение объектов в СУБД Ссылки на объекты (OBJECT REF) <Insert Picture Here> Инкапсуляция Атрибуты типа Объектный тип 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 Статический метод Инкапсуляция Объектный тип 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 Переменные объектного типа Использование 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 Наследование Наследование типов 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 Наследование Пример: визуальное представление • Перегрузка метода сохранения объекта (save) TObject save TPersistent Абстрактный метод save TAccount Перегруженный метод 9 Полиморфизм Перегрузка методов в типе-потомке 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 Не терминальный тип в иерархии ! Полиморфизм Вызов унаследованного метода в типе-потомке 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 Ограничения в ООП 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 Дополнительные возможности Приведение типов - 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 Дополнительные возможности Перегрузка операторов сравнения • Необходимо реализовать метод сравнения 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 Дополнительные возможности Коллекции объектов • Создаются на уровне СУБД: 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 • <>, = - проверяет две коллекции на (не) равенство; • SET – удаляет дубликаты из коллекции; • [NOT] MEMBER – проверка вхождения элемента; • MULTISET INTERSECT – пересечение коллекций; • MULTISET UNION – объединение коллекций; • MULTISET EXCEPT – из одной вычесть другую; • IS A [NOT] SET – содержит уникальные элементы; • NOT SUBMULTISET OF – проверка на подмножество; Дополнительные возможности Коллекции объектов - использование • Для использования операторов с коллекциями, объектный тип должен иметь метод 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 Хранение объектов в БД Объектные таблицы • Объектные таблицы 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 Ссылки на объекты 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 Ссылки на объекты Дополнительные возможности • Дополнительный пакет 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 Рефлексия объектных типов в PL/SQL 21 Generic PL/SQL types Обобщенные типы • ANYTYPE – получение информации о типе, а также создание анонимных типов • ANYDATA – представляет собой экземпляр любого типа • ANYDATASET - представляет собой множество экземпляров какого-либо типа (generic recordset) • DBMS_TYPES – пакет (package) предоставляет набор констант и исключений для работы с обобщенными типами 22 Тип 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 Тип 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 Тип 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 Тип ANYDATA Получение информации об экземпляре типа • BEGINCREATE – начало создания нового экземпляра AnyData • ENDCREATE – завершение создания экземпляра AnyData • PIECEWISE – установка режима создания экземпляра для не примитивных объектов • SET* – установить значение атрибута • GET* – получение значения атрибута • GETTYPENAME– получить имя типа (для типов уже существующих в БД) • GETTYPE – получение экземпляра ANYTYPE описывающего тип объекта • CONVERTOBJECT – получение экземпляра ANYDATA из любого объекта 26 Два способа создания экз. 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 Два способа создания экз. 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 Тип 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 Тип ANYDATASET Интерфейс ODCITable – информация для SQL-Engine • • • • • 30 ODCITableDescribe – возвращает структуру курсора ODCITableStart – открытие курсора ODCITableFetch – извлечение записи ODCITableClose – закрытие курсора ODCIPrepare – получение контекста выполнения курсора Интерфейс 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 Паттерны проектирования в PL/SQL 32 Шаблон “Одиночка” (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 Шаблон “Наблюдатель” (Observer) Шаблон “Наблюдатель” 34 Шаблон “Наблюдатель” (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 Шаблон “Наблюдатель” (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 Шаблон “Наблюдатель” (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 Шаблон “Фабричный метод” 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/ СУБД Oracle Database как фабрика и репозитарий объектов 39 Недостатки хранения объектов Хранение в объектных таблицах Oracle • Крайне затруднена модификация исх. кода объектов (есть связь с таблицей!) • Сложный синтаксис обращения к объектной таблице • Изменение атрибутов объекта ведет к тяжелой процедуре модификации структуры объектной таблицы 40 Хранение объектов в реляц. таблицах Совмещение преимуществ ООП и реляционного подхода • Хранить Persistent-объекты в обычных реляционных таблицах • Доступ реализовать в виде обычного реляционного SQL, в коде методов объектного типа • Когда необходимо, применять обычный реляционный доступ к таблицам 41 Репозитарий объектов в СУБД Oracle 42 Репозитарий объектов в Oracle Базовая иерархия классов 43 Работа с репозитарием Тип 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 Работа с объектами в приложении Пример: 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 Oracle Developer Tools for VS .NET UDT Custom Class Code Generation Wizard 46 Custom Class Code Generation Wizard Прозрачное использование объекта в приложении 47 Пример реализации универсальной библиотеки типов PL/SQL 48 Постановка задачи Необходимость в библиотеке • Поддержки репозитария объектов недостаточно ! • Часто приходится повторять один и тот же код: • • • • • Работа с списками Работа с хеш-таблицами Обработка массива строк Обработка исключений И т.д. • Необходима библиотека универсальных (проблемнонезависимых) типов – по аналогии с JDK, .NET, VCL и т.д. 49 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 Работа с списками строк в 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 Обработка исключений Пример: использование типов-исключений 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 Инкапсуляция функций 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 Работа с объектной моделью 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 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 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 PL/SQL Class Library 57 Использование PL/SQL-типов в APEX 58 ООП PL/SQL Заключение • Поддерживает все основные парадигмы ООП • Позволяет создавать прикладное ПО в ООстиле и получить все преимущества ООПподхода • Наличие библиотеки PL/SQL-типов позволяет достичь повторного использования кода, уменьшить сложность проектов и сократить время разработки 59 60 <Insert Picture Here> Игорь Мельников Старший консультант Oracle СНГ Email: Igor.Melnikov@oracle.com Phone: +7 (495) 641 14 00 Direct: +7 (495) 641 14 42 Mobile: +7 (915) 205 26 27 62