Spec-Zone .ru
спецификации, руководства, описания, API
След: JDBC (ТМ) Доступ к базе данных
Урок: Основы JDBC
Используя Структурированные Объекты
Домашняя страница > JDBC (ТМ) Доступ к базе данных > Основы JDBC

Используя Структурированные Объекты

Отметьте: MySQL и DB Java в настоящий момент не поддерживают определяемые пользователем типы. Следовательно, никакой учебный пример JDBC не доступен, чтобы демонстрировать функции, описанные в этом разделе.

Следующие темы затрагиваются:

Краткий обзор Структурированных Типов

SQL структурированные типы и DISTINCT типы являются двумя типами данных, которые пользователь может определить в SQL. Они часто упоминаются как UDTs (определяемые пользователем типы), и Вы создаете их с SQL CREATE TYPE оператор.

Возвращаясь к примеру Перерыва на кофе, предположите, что владелец был успешен вне всех ожиданий и расширялся с новыми ответвлениями. Владелец решил добавить a STORES таблица к базе данных, содержащей информацию о каждом установлении. STORES будет иметь четыре столбца:

Владелец делает столбец LOCATION будьте SQL структурированный тип, столбец COF_TYPES SQL ARRAY, и столбец MGR a REF(MANAGER), с MANAGER будучи SQL структурированный тип.

Первая вещь владелец должна определить новые структурированные типы для адреса и менеджера. SQL структурированный тип подобен структурированному, вводит язык программирования Java, в котором у этого есть элементы, названные атрибутами, которые могут быть любым типом данных. Владелец пишет следующий SQL-оператор, чтобы создать новый тип данных ADDRESS:

CREATE TYPE ADDRESS
(
    NUM INTEGER,
    STREET VARCHAR(40),
    CITY VARCHAR(40),
    STATE CHAR(2),
    ZIP CHAR(5)
);

В этом операторе, новом типе ADDRESS имеет пять атрибутов, которые походят на поля в Java class. Атрибут NUM INTEGER, атрибут STREET a VARCHAR(40), атрибут CITY a VARCHAR(40), атрибут STATE a CHAR(2), и атрибут ZIP a CHAR(5).

Следующая выборка та, в который con допустимое Connection возразите, отправляет определение ADDRESS к базе данных:

String createAddress =
    "CREATE TYPE ADDRESS " +
    "(NUM INTEGER, STREET VARCHAR(40), " +
    "CITY VARCHAR(40), STATE CHAR(2), ZIP CHAR(5))";
Statement stmt = con.createStatement();
stmt.executeUpdate(createAddress);

Теперь ADDRESS структурированный тип регистрируется в базе данных как тип данных, и владелец может использовать это в качестве типа данных для столбца таблицы или атрибута структурированного типа.

Используя ОТЛИЧНЫЙ Тип в Структурированном Типе

Один из атрибутов владелец Перерыва на кофе планирует включать в новый структурированный тип MANAGER номер телефона менеджера. Поскольку владелец будет всегда перечислять номер телефона как 10-разрядное число (чтобы убедиться, что он включает код области), и никогда не будет управлять этим как числом, владелец решает определить новый вызванный тип PHONE_NO это состоит из 10 символов. Определение SQL этого типа данных, который может считаться структурированным типом только с одним атрибутом, похоже на это:

CREATE TYPE PHONE_NO AS CHAR(10);

Или, как отмечено ранее, для некоторых драйверов определение могло бы быть похожим на это:

CREATE DISTINCT TYPE PHONE_NO AS CHAR(10);

A DISTINCT тип всегда основан на другом типе данных, который должен быть предварительно определенным типом. Другими словами, a DISTINCT тип не может быть основан на определяемом пользователем типе (UDT). Получить или установить значение, которое является a DISTINCT введите, используйте соответствующий метод для базового типа (тип, на котором это базируется). Например, чтобы получить экземпляр PHONE_NO, который основан на a CHAR введите, Вы использовали бы метод getString потому что это - метод для того, чтобы получить a CHAR.

Предположение, что значение типа PHONE_NO находится в четвертом столбце текущей строки ResultSet объект rs, следующая строка кода получает это:

String phoneNumber = rs.getString(4);

Точно так же следующая строка кодовых наборов входной параметр, у которого есть тип PHONE_NO для готового оператора, отправляемого базе данных:

pstmt.setString(1, phoneNumber);

Прибавляя к предыдущему фрагменту кода, определению PHONE_NO будет отправлен базе данных со следующей строкой кода:

stmt.executeUpdate(
    "CREATE TYPE PHONE_NO AS CHAR(10)");

После регистрации типа PHONE_NO с базой данных владелец может использовать это, поскольку столбец вводит таблицу или как тип данных для атрибута в структурированном типе. Определение MANAGER в следующем использовании SQL-оператора PHONE_NO как тип данных для атрибута PHONE:

CREATE TYPE MANAGER
(
    MGR_ID INTEGER,
    LAST_NAME VARCHAR(40),
    FIRST_NAME VARCHAR(40),
    PHONE PHONE_NO
);

Многократное использование stmt, определенный ранее, следующий фрагмент кода отправляет определение структурированного типа MANAGER к базе данных:

  String createManager =
    "CREATE TYPE MANAGER " +
    "(MGR_ID INTEGER, LAST_NAME " +
    "VARCHAR(40), " +
    "FIRST_NAME VARCHAR(40), " +
    "PHONE PHONE_NO)";
  stmt.executeUpdate(createManager);

Используя Ссылки на Структурированные Типы

Владелец Перерыва на кофе создал три новых типа данных, используемые в качестве типов столбца, или атрибут вводит базу данных: структурированные типы LOCATION и MANAGER, и DISTINCT ввести PHONE_NO. Предприниматель использовал PHONE_NO как тип для атрибута PHONE в новом типе MANAGER, и ADDRESS как тип данных для столбца LOCATION в таблице STORES. MANAGER тип мог использоваться в качестве типа для столбца MGR, но вместо этого предприниматель предпочитает использовать тип REF(MANAGER) потому что предприниматель часто сделал, чтобы один человек управлял двумя или тремя хранилищами. Используя REF(MANAGER) поскольку тип столбца избегает повторять все данные для MANAGER когда один человек управляет больше чем одним хранилищем.

Со структурированным типом MANAGER уже создаваемый, владелец может теперь составить таблицу, содержащую экземпляры MANAGER на это можно сослаться. Ссылка на экземпляр MANAGER будет иметь тип REF(MANAGER). SQL REF не что иное как логический указатель на структурированный тип, таким образом, экземпляр REF(MANAGER) служит логическим указателем на экземпляр MANAGER.

Поскольку SQL REF оцените должен быть постоянно связан с экземпляром структурированного типа, на который он ссылается, он сохранен в специальной таблице вместе с ее связанным экземпляром. Программист не создает REF типы непосредственно, а скорее составляют таблицу, которая сохранит экземпляры определенного структурированного типа, на который можно сослаться. У каждого структурированного типа, на который нужно сослаться, будет своя собственная таблица. Когда Вы вставляете экземпляр структурированного типа в таблицу, база данных автоматически создает a REF экземпляр. Например, чтобы содержать экземпляры MANAGER на это можно сослаться, владелец, создаваемый следующая специальная таблица, используя SQL:

  CREATE TABLE MANAGERS OF MANAGER
  (OID REF(MANAGER)
  VALUES ARE SYSTEM GENERATED);

Этот оператор составляет таблицу со специальным столбцом OID, который хранит значения типа REF(MANAGER). Каждый раз экземпляр MANAGER вставляется в таблицу, база данных генерирует экземпляр REF(MANAGER) и сохраните это в столбце OID. Неявно, дополнительный столбец хранит каждый атрибут MANAGER это было вставлено в таблицу, также. Например, следующий фрагмент кода показывает как предприниматель, создаваемый три экземпляра MANAGER структурированный тип, чтобы представить трех менеджеров:

  INSERT INTO MANAGERS (
    MGR_ID, LAST_NAME,
    FIRST_NAME, PHONE) VALUES
  (
    000001,
    'MONTOYA',
    'ALFREDO',
    '8317225600'
  );

  INSERT INTO MANAGERS (
    MGR_ID, LAST_NAME,
    FIRST_NAME, PHONE) VALUES
  (
    000002,
    'HASKINS',
    'MARGARET',
    '4084355600'
  );

  INSERT INTO MANAGERS (
    MGR_ID, LAST_NAME,
    FIRST_NAME, PHONE) VALUES
  (
    000003,
    'CHEN',
    'HELEN',
    '4153785600'
   );

Таблица MANAGERS будет теперь иметь три строки, одну строку для каждого менеджера вставленными до сих пор. Столбец OID будет содержать три уникальных объектных идентификатора типа REF(MANAGER), один для каждого экземпляра MANAGER. Эти объектные идентификаторы были сгенерированы автоматически базой данных и будут постоянно сохранены в таблице MANAGERS. Неявно, дополнительный столбец хранит каждый атрибут MANAGER. Например, в таблице MANAGERS, одна строка содержит a REF(MANAGER) это ссылается на Альфредо Монтойя, другая строка содержит a REF(MANAGER) это ссылается на Маргарет Хэскинс, и третья строка содержит a REF(MANAGER) это ссылается на Хелен Чен.

К доступу a REF(MANAGER) экземпляр, Вы выбираете это из его таблицы. Например, владелец, полученный ссылка на Альфредо Монтойя, Идентификационный номер которого 000001 со следующим фрагментом кода:

  String selectMgr =
    "SELECT OID FROM MANAGERS " +
    "WHERE MGR_ID = 000001";
  ResultSet rs = stmt.executeQuery(selectMgr);
  rs.next();
  Ref manager = rs.getRef("OID");

Теперь переменная manager может использоваться в качестве значения столбца, это ссылается на Альфредо Монтойя.

Пример кода для Создания SQL КАСАТЕЛЬНО Объекта

Следующий пример кода составляет таблицу MANAGERS, таблица экземпляров структурированного типа MANAGER на это можно сослаться, и вставляет три экземпляра MANAGER в таблицу. Столбец OID в этой таблице сохранит экземпляры REF(MANAGER). После того, как этот код выполняется, MANAGERS таблица поссорится для каждого из трех MANAGER объекты, вставленные, и значение в OID столбец будет REF(MANAGER) введите, который идентифицирует экземпляр MANAGER сохраненный в той строке.

package com.oracle.tutorial.jdbc;

import java.sql.*;

public class CreateRef {

    public static void main(String args[]) {

        JDBCTutorialUtilities myJDBCTutorialUtilities;
        Connection myConnection = null;

        if (args[0] == null) {
            System.err.println("Properties file not specified " +
                               "at command line");
            return;
        } else {
            try {
                myJDBCTutorialUtilities = new JDBCTutorialUtilities(args[0]);
            } catch (Exception e) {
                System.err.println("Problem reading properties " +
                                   "file " + args[0]);
                e.printStackTrace();
                return;
            }
        }

        Connection con = null;
        Statement stmt = null;

        try {
            String createManagers =
                "CREATE TABLE " +
                "MANAGERS OF MANAGER " +
                "(OID REF(MANAGER) " +
                "VALUES ARE SYSTEM " +
                "GENERATED)";

            String insertManager1 =
                "INSERT INTO MANAGERS " +
                "(MGR_ID, LAST_NAME, " +
                "FIRST_NAME, PHONE) " +
                "VALUES " +
                "(000001, 'MONTOYA', " +
                "'ALFREDO', " +
                "'8317225600')";

            String insertManager2 =
                "INSERT INTO MANAGERS " +
                "(MGR_ID, LAST_NAME, " +
                "FIRST_NAME, PHONE) " +
                "VALUES " +
                "(000002, 'HASKINS', " +
                "'MARGARET', " +
                "'4084355600')";

            String insertManager3 =
                "INSERT INTO MANAGERS " +
                "(MGR_ID, LAST_NAME, " +
                "FIRST_NAME, PHONE) " +
                "VALUES " +
                "(000003, 'CHEN', 'HELEN', " +
                "'4153785600')";
  
            con = myJDBCTutorialUtilities.getConnection();
            con.setAutoCommit(false);

            stmt = con.createStatement();
            stmt.executeUpdate(createManagers);

            stmt.addBatch(insertManager1);
            stmt.addBatch(insertManager2);
            stmt.addBatch(insertManager3);
            int [] updateCounts = stmt.executeBatch();

            con.commit();

            System.out.println("Update count for:  ");
            for (int i = 0; i < updateCounts.length; i++) {
                System.out.print("    command " + (i + 1) + " = ");
                System.out.println(updateCounts[i]);
            }
        } catch(BatchUpdateException b) {
            System.err.println("-----BatchUpdateException-----");
            System.err.println("Message:  " + b.getMessage());
            System.err.println("SQLState:  " + b.getSQLState());
            System.err.println("Vendor:  " + b.getErrorCode());
            System.err.print("Update counts for " + "successful commands:  ");
            int [] rowsUpdated = b.getUpdateCounts();
            for (int i = 0; i < rowsUpdated.length; i++) {
                System.err.print(rowsUpdated[i] + "   ");
            }
            System.err.println("");
        } catch(SQLException ex) {
            System.err.println("------SQLException------");
            System.err.println("Error message:  " + ex.getMessage());
            System.err.println("SQLState:  " + ex.getSQLState());
            System.err.println("Vendor:  " + ex.getErrorCode());
        } finally {
            if (stmt != null) { stmt.close(); }
              JDBCTutorialUtilities.closeConnection(con);
        }
    }
}

Используя Определяемые пользователем Типы как Значения столбцов

У нашего предпринимателя теперь есть UDTs, требуемый составлять таблицу STORES. Структурированный тип ADDRESS тип для столбца LOCATION, и тип REF(MANAGER) тип для столбца MGR.

UDT COF_TYPES основано на типе данных SQL ARRAY и тип для столбца COF_TYPES. Следующая строка кода создает тип COF_ARRAY как ARRAY значение с 10 элементами. Базовый тип COF_ARRAY VARCHAR(40).

  CREATE TYPE COF_ARRAY AS ARRAY(10) OF VARCHAR(40);

С новыми определенными типами данных следующий SQL-оператор составляет таблицу STORES:

  CREATE TABLE STORES
  (
    STORE_NO INTEGER,
    LOCATION ADDRESS,
    COF_TYPES COF_ARRAY,
    MGR REF(MANAGER)
  );

Вставка Определяемых пользователем Типов в Таблицы

Следующий фрагмент кода вставляет одну строку в STORES таблица, предоставляя значения для столбцов STORE_NO, LOCATION, COF_TYPES, и MGR, в том порядке:

  INSERT INTO STORES VALUES
  (
    100001,
    ADDRESS(888, 'Main_Street',
      'Rancho_Alegre',
      'CA', '94049'),
    COF_ARRAY('Colombian', 'French_Roast',
      'Espresso', 'Colombian_Decaf',
      'French_Roast_Decaf'),
    SELECT OID FROM MANAGERS
      WHERE MGR_ID = 000001
  );

Следующее проходит через каждый столбец и значение, вставленное в это.

  STORE_NO: 100001

Этот столбец является типом INTEGER, и число 100001 INTEGER введите, подобный записям, сделанным прежде в таблицах COFFEES и SUPPLIERS.

  LOCATION: ADDRESS(888, 'Main_Street',
    'Rancho_Alegre', 'CA', '94049')

Тип для этого столбца является структурированным типом ADDRESS, и это значение является конструктором для экземпляра ADDRESS. Когда мы отправили определение ADDRESS был отправлен базе данных, одна из вещей, которые это сделало, состояла в том, чтобы создать конструктора для нового типа. Разделенные от запятой значения в круглых скобках являются значениями инициализации для атрибутов ADDRESS введите, и они должны появиться в том же самом порядке, в котором атрибуты были перечислены в определении ADDRESS ввести. 888 значение для атрибута NUM, который является INTEGER значение. "Main_Street" значение для STREET, и "Rancho_Alegre" значение для CITY, с обоими атрибутами, имеющими тип VARCHAR(40). Значение для атрибута STATE "CA", который имеет тип CHAR(2), и значение для атрибута ZIP "94049", который имеет тип CHAR(5).

  COF_TYPES: COF_ARRAY(
    'Colombian',
    'French_Roast',
    'Espresso',
    'Colombian_Decaf',
    'French_Roast_Decaf'),

Столбец COF_TYPES имеет тип COF_ARRAY с базовым типом VARCHAR(40), и разделенные от запятой значения между круглыми скобками String объекты, которые являются элементами массива. Владелец, определенный тип COF_ARRAY как наличие максимума 10 элементов. У этого массива есть 5 элементов потому что предприниматель, предоставленный только 5 String объекты для этого.

  MGR: SELECT OID FROM MANAGERS
    WHERE MGR_ID = 000001

Столбец MGR тип REF(MANAGER), что означает, что значение в этом столбце должно быть ссылкой на структурированный тип MANAGER. Все экземпляры MANAGER сохранены в таблице MANAGERS. Все экземпляры REF(MANAGER) также сохранены в этой таблице, в столбце OID. Менеджером по хранилищу, описанному в этой строке таблицы, является Альфредо Монтойя, и его информация хранится в экземпляре MANAGER это имеет 100001 для атрибута MGR_ID. Добраться REF(MANAGER) экземпляр, связанный с MANAGER объект для Альфредо Монтойя, выберите столбец OID это находится в строке где MGR_ID 100001 в таблице MANAGERS. Значение, которое будет сохранено в MGR столбец STORES таблица ( REF(MANAGER) значение), значение DBMS, сгенерированный, чтобы однозначно определить этот экземпляр MANAGER структурированный тип.

Отправьте предыдущий SQL-оператор базе данных со следующим фрагментом кода:

  String insertMgr =
    "INSERT INTO STORES VALUES " +
    "(100001, " +
    "ADDRESS(888, 'Main_Street', " +
      "'Rancho_Alegre', 'CA', " +
      "'94049'), " +
    "COF_ARRAY('Colombian', " +
      "'French_Roast', 'Espresso', " +
      "'Colombian_Decaf', " +
      "'French_Roast_Decaf'}, " +
    "SELECT OID FROM MANAGERS " +
    "WHERE MGR_ID = 000001)";

  stmt.executeUpdate(insertMgr);

Однако, потому что Вы собираетесь отправить несколько INSERT INTO операторы, будет более эффективно отправить им всем вместе как пакетное обновление, как в следующем примере кода:

package com.oracle.tutorial.jdbc;

import java.sql.*;

public class InsertStores {
    public static void main(String args[]) {

        JDBCTutorialUtilities myJDBCTutorialUtilities;
        Connection myConnection = null;

        if (args[0] == null) {
            System.err.println(
                "Properties file " +
                "not specified " +
                "at command line");
            return;
        } else {
            try {
                myJDBCTutorialUtilities = new
                    JDBCTutorialUtilities(args[0]);
            } catch (Exception e) {
                System.err.println(
                    "Problem reading " +
                    "properties file " +
                    args[0]);
                e.printStackTrace();
                return;
            }
        }

        Connection con = null;
        Statement stmt = null;

        try {
            con = myJDBCTutorialUtilities.getConnection();
            con.setAutoCommit(false);

            stmt = con.createStatement();

            String insertStore1 =
                "INSERT INTO STORES VALUES (" +
                "100001, " +
                "ADDRESS(888, 'Main_Street', " +
                    "'Rancho_Alegre', 'CA', " +
                    "'94049'), " +
                "COF_ARRAY('Colombian', " +
                    "'French_Roast', " +
                    "'Espresso', " +
                    "'Colombian_Decaf', " +
                    "'French_Roast_Decaf'), " +
                "(SELECT OID FROM MANAGERS " +
                "WHERE MGR_ID = 000001))";

            stmt.addBatch(insertStore1);

            String insertStore2 =
                "INSERT INTO STORES VALUES (" +
                "100002, " +
                "ADDRESS(1560, 'Alder', " +
                    "'Ochos_Pinos', " +
                    "'CA', '94049'), " +
                "COF_ARRAY('Colombian', " +
                    "'French_Roast', " +
                    "'Espresso', " +
                    "'Colombian_Decaf', " +
                    "'French_Roast_Decaf', " +
                    "'Kona', 'Kona_Decaf'), " +
                "(SELECT OID FROM MANAGERS " +
                "WHERE MGR_ID = 000001))";

            stmt.addBatch(insertStore2);

            String insertStore3 =
                "INSERT INTO STORES VALUES (" +
                "100003, " +
                "ADDRESS(4344, " +
                    "'First_Street', " +
                    "'Verona', " +
                    "'CA', '94545'), " +
                "COF_ARRAY('Colombian', " +
                    "'French_Roast', " +
                    "'Espresso', " +
                    "'Colombian_Decaf', " +
                    "'French_Roast_Decaf', " +
                    "'Kona', 'Kona_Decaf'), " +
                "(SELECT OID FROM MANAGERS " +
                "WHERE MGR_ID = 000002))";

            stmt.addBatch(insertStore3);

            String insertStore4 =
                "INSERT INTO STORES VALUES (" +
                "100004, " +
                "ADDRESS(321, 'Sandy_Way', " +
                    "'La_Playa', " +
                    "'CA', '94544'), " +
                "COF_ARRAY('Colombian', " +
                    "'French_Roast', " +
                    "'Espresso', " +
                    "'Colombian_Decaf', " +
                    "'French_Roast_Decaf', " +
                    "'Kona', 'Kona_Decaf'), " +
                "(SELECT OID FROM MANAGERS " +
                "WHERE MGR_ID = 000002))";

            stmt.addBatch(insertStore4);

            String insertStore5 =
                "INSERT INTO STORES VALUES (" +
                "100005, " +
                "ADDRESS(1000, 'Clover_Road', " +
                    "'Happyville', " +
                    "'CA', '90566'), " +
                "COF_ARRAY('Colombian', " +
                    "'French_Roast', " +
                    "'Espresso', " + 
                    "'Colombian_Decaf', " +
                    "'French_Roast_Decaf'), " +
                "(SELECT OID FROM MANAGERS " +
                "WHERE MGR_ID = 000003))";

            stmt.addBatch(insertStore5);

            int [] updateCounts = stmt.executeBatch();

            ResultSet rs = stmt.executeQuery(
                "SELECT * FROM STORES");
            System.out.println("Table STORES after insertion:");
            System.out.println("STORE_NO   " + "LOCATION   " +
                "COF_TYPE   " + "MGR");

            while (rs.next()) {
                int storeNo = rs.getInt("STORE_NO");
                Struct location = (Struct)rs.getObject("LOCATION");
                Object[] locAttrs = location.getAttributes();
                Array coffeeTypes = rs.getArray("COF_TYPE");
                String[] cofTypes = (String[])coffeeTypes.getArray();

                Ref managerRef = rs.getRef("MGR");
                PreparedStatement pstmt = con.prepareStatement(
                    "SELECT MANAGER " +
                    "FROM MANAGERS " +
                    "WHERE OID = ?");
  
                pstmt.setRef(1, managerRef);
                ResultSet rs2 = pstmt.executeQuery();
                rs2.next();
                Struct manager = (Struct)rs2.getObject("MANAGER");
                Object[] manAttrs = manager.getAttributes();
      
                System.out.print(storeNo + "   ");
                System.out.print(
                    locAttrs[0] + " " +
                    locAttrs[1] + " " +
                    locAttrs[2] + ", " +
                    locAttrs[3] + " " +
                    locAttrs[4] + " ");

                for (int i = 0; i < cofTypes.length; i++)
                    System.out.print( cofTypes[i] + " ");
          
                System.out.println(
                    manAttrs[1] + ", " +
                    manAttrs[2]);
        
                rs2.close();
                pstmt.close();
            }

            rs.close();

        } catch(BatchUpdateException b) {
            System.err.println("-----BatchUpdateException-----");
            System.err.println("SQLState:  " + b.getSQLState());
            System.err.println("Message:  " + b.getMessage());
            System.err.println("Vendor:  " + b.getErrorCode());
            System.err.print("Update counts:  ");
            int [] updateCounts = b.getUpdateCounts();

            for (int i = 0; i < updateCounts.length; i++) {
                System.err.print(updateCounts[i] + "   ");
            }
            System.err.println("");

        } catch(SQLException ex) {
            System.err.println("SQLException: " + ex.getMessage());
            System.err.println("SQLState:  " + ex.getSQLState());
            System.err.println("Message:  " + ex.getMessage());
            System.err.println("Vendor:  " + ex.getErrorCode());
        } finally {
            if (stmt != null) { stmt.close(); }
                JDBCTutorialUtilities.closeConnection(con);
            }
        }
    }
}

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Используя ОТЛИЧНЫЙ Тип данных
Следующая страница: Используя Специализированные Отображения Типа