Статьи

Создание сервисов данных WSO2 EI с базой данных Sybase

Создание сервисов данных WSO2 EI с базой данных Sybase

Этот пост покажет быстрый пример того, как мы можем соединиться с базой данных Sybase с помощью WSO2 EI DataServices. Для этого поста мы использовали WSO2 EI 6.5.0, но он должен работать и с EI 7. Итак, начнем.


Вы также можете быть заинтересованы в: 
WSO2 Enterprise Integrator для распределенных сообщений

Запуск локального экземпляра Sybase

Чтобы этот пример работал, нам нужен экземпляр Sybase. Для этого мы будем использовать следующий образ Docker, доступный в Docker Hub: datagrip / sybase . Этот образ Docker содержит Sybase 16.2, для его запуска нам просто нужно выполнить следующую команду:

docker run -d -t -p 5000:5000 datagrip/sybase

Через некоторое время, ~ 30 с, мы можем подключиться к экземпляру Sybase. Учетные данные по умолчанию можно найти на странице образа Docker в Docker Hub. Мы можем использовать клиент SQL для подключения к нему; хороший — это DBeaver.

В нашем примере мы свяжемся с пользователем admin (sa). В DBeaver детали подключения будут выглядеть следующим образом:

DBeaver Connection

После подключения мы можем увидеть список доступных схем базы данных:

DBeaver Базы данных

Для нашего примера мы будем использовать схему testdb. Мы создадим таблицу продуктов, как показано ниже:

CREATE TABLE testdb.dbo.product ( 
ID BIGINT IDENTITY,
name VARCHAR(255), 
description VARCHAR(244),
price DECIMAL,
PRIMARY KEY(ID)
);

Команда выше создаст таблицу в схеме testdb.

Подключение WSO2 EI к базе данных Sybase

Мы можем подключиться к Sybase с помощью JDBC, и мы можем использовать драйвер JTDS или драйвер JConnect. В нашем примере мы будем использовать драйвер JConnect. Я не смог найти ссылку для ее загрузки (по моей вине, мне было лень ее искать), но у нас она есть в контейнере Sybase, который мы начали на предыдущих шагах. Для этого мы можем использовать команду docker cp , но нам нужен идентификатор контейнера. Чтобы получить идентификатор контейнера, мы можем использовать команду docker ps . Ниже мы можем увидеть результат:

CONTAINER ID        IMAGE   ....
2bb8d9f01869        datagrip/sybase    ...

Итак, чтобы скопировать jar драйвера JDBC из контейнера на наш локальный компьютер, мы можем использовать следующую команду:

docker cp [CONTAINER ID]:/opt/sybase/shared/lib/jconn4.jar .

Приведенная выше команда скопирует jconn4.jar из этого расположения в текущую папку на локальном компьютере. Нам нужно заменить [CONTAINER ID] на идентификатор, полученный в выводе команды docker ps.

Когда у нас есть файл jar, нам нужно скопировать его в папку [WSO2_EI_HOME] / lib . После этого нам нужно перезапустить EI-сервер, чтобы загрузить файл JAR.

Теперь, когда мы скопировали файл jar в установку EI и перезапустили его, мы можем создать новый источник данных, указывающий на сервер Sybase. В этом примере мы создадим источник данных с помощью пользовательского интерфейса Carbon Console, но вы можете найти другие способы его создания здесь .

Для создания источника данных нам необходимо:

  1. Войти в Carbon: https: // localhost: 9443 / carbon
  2. Перейдите на вкладку «Настройка» -> «Источники данных» и нажмите «Добавить источник данных»:Carbon Console Datasource
  3. Заполните данные источника данных, как показано ниже:
  • Тип источника данных: СУБД
  • Имя: Sybase
  • Поставщик источника данных: по умолчанию
  • СУБД: Sybase ASE
  • Драйвер: com.sybase.jdbc4.jdbc.SybDriver
  • URL: jdbc: sybase: Tds: localhost: 5000 / testdb
  • Имя пользователя: sa
  • Пароль: мой пароль

Carbon Console Новый источник данных

Если все настроено правильно, когда мы нажимаем на Test Connection, оно должно быть успешным. После этого мы можем нажать «Сохранить».

Создание Dataservice

Полный код примера, который мы создадим, можно увидеть ниже:

<data name="SybaseTest" transports="http https local">
   <config enableOData="false" id="Sybase">
      <property name="carbon_datasource_name">Sybase</property>
   </config>
   <query id="Query_All_Products" useConfig="Sybase">
      <sql>Select ID,name ,description, price from testdb.dbo.product</sql>
      <result element="Products" rowName="Product">
         <element column="id" name="id" xsdType="string"/>
         <element column="name" name="name" xsdType="string"/>
         <element column="description" name="description" xsdType="string"/>
         <element column="price" name="price" xsdType="decimal"/>
      </result>
   </query>
   <query id="GetRoles" useConfig="Sybase">
      <sql>exec sp_activeroles</sql>
      <result element="Roles" rowName="Role">
         <element column="Role Name" name="RoleName" xsdType="string"/>
      </result>
   </query>
   <query id="GetColumns" useConfig="Sybase">
      <sql>exec sp_columns ?, ?, ?, ?</sql>
      <result element="Columns" rowName="Column">
         <element column="column_name" name="ColumnName" xsdType="string"/>
         <element column="type_name" name="TypeName" xsdType="string"/>
      </result>
      <param name="table_name" optional="false" sqlType="STRING"/>
      <param defaultValue="#{NULL}" name="table_owner" optional="true" sqlType="STRING"/>
      <param defaultValue="#{NULL}" name="table_qualifier" optional="true" sqlType="STRING"/>
      <param defaultValue="#{NULL}" name="column_name" optional="true" sqlType="STRING"/>
   </query>
   <operation name="QueryAllProducts">
      <call-query href="Query_All_Products"/>
   </operation>
   <operation name="GetColumns">
      <call-query href="GetColumns">
         <with-param name="table_name" query-param="table_name"/>
         <with-param name="table_owner" query-param="table_owner"/>
         <with-param name="table_qualifier" query-param="table_qualifier"/>
         <with-param name="column_name" query-param="column_name"/>
      </call-query>
   </operation>
   <resource method="GET" path="/products">
      <call-query href="Query_All_Products"/>
   </resource>
   <resource method="GET" path="/roles">
      <call-query href="GetRoles"/>
   </resource>
   <resource method="GET" path="/columns">
      <call-query href="GetColumns">
         <with-param name="table_name" query-param="table_name"/>
         <with-param name="table_owner" query-param="table_owner"/>
         <with-param name="table_qualifier" query-param="table_qualifier"/>
         <with-param name="column_name" query-param="column_name"/>
      </call-query>
   </resource>
</data>

В приведенном выше Dataservice мы имеем 3 операции:

  • Выбор в таблице
  • Вызов хранимой процедуры без параметров
  • Вызов хранимой процедуры с параметрами

Выполнение запроса Sybase Select

Это очень похоже на любой запрос выбора в других RDBMS. Мы можем увидеть детали ниже:

Мы можем увидеть запрос, операцию (SOAP) и ресурс (REST) ​​для этого:

<query id="Query_All_Products" useConfig="Sybase">
    <sql>Select ID,name ,description, price from testdb.dbo.product</sql>
    <result element="Products" rowName="Product">
        <element column="id" name="id" xsdType="string"/>
        <element column="name" name="name" xsdType="string"/>
        <element column="description" name="description" xsdType="string"/>
        <element column="price" name="price" xsdType="decimal"/>
    </result>
</query>
...
<operation name="QueryAllProducts">
    <call-query href="Query_All_Products"/>
</operation>

<resource method="GET" path="/products">
    <call-query href="Query_All_Products"/>
</resource>

По сути, мы определяем запрос к таблице продукта и сопоставляем столбцы, возвращаемые в запросе, с ожидаемыми атрибутами в ответе. Мы определяем SOAP-операцию QueryAllProducts и Rest Resource / products; оба они указывают на один и тот же запрос.

Имея это в виду, мы можем вызвать, например, ресурсы / products, как показано ниже:

http://localhost:8280/services/SybaseTest/products

У нас будет возврат, как показано ниже:

<Products xmlns="http://ws.wso2.org/dataservice">
    <Product>
        <id>1</id>
        <name>Book</name>
        <description>Wonderful book</description>
        <price>10</price>
    </Product>
</Products>

Выполнение хранимой процедуры без параметров

В этом запросе мы выполняем существующую хранимую процедуру в Sybase, в данном случае  sp_activeroles.  Чтобы вызвать его, мы используем exec:

exec sp_activeroles

Этот вызов вернет набор результатов только с одним столбцом «Имя роли». Запрос и ресурс можно увидеть ниже:

<query id="GetRoles" useConfig="Sybase">
    <sql>exec sp_activeroles</sql>
    <result element="Roles" rowName="Role">
        <element column="Role Name" name="RoleName" xsdType="string"/>
    </result>
</query>

<resource method="GET" path="/roles">
    <call-query href="GetRoles"/>
</resource>

Приведенная выше конфигурация предоставит ресурс / роли, которые мы можем вызвать, используя конечную точку ниже:

http://localhost:8280/services/SybaseTest/roles

Это вернет полезную нагрузку, как показано ниже:

<?xml version="1.0" encoding="UTF-8"?>
<Roles xmlns="http://ws.wso2.org/dataservice">
    <Role>
        <RoleName>sa_role</RoleName>
    </Role>
    <Role>
        <RoleName>sso_role</RoleName>
    </Role>
    <Role>
        <RoleName>oper_role</RoleName>
    </Role>
    <Role>
        <RoleName>sybase_ts_role</RoleName>
    </Role>
    <Role>
        <RoleName>mon_role</RoleName>
    </Role>
    <Role>
        <RoleName>sa_serverprivs_role</RoleName>
    </Role>
</Roles>

Выполнение хранимой процедуры с параметрами

В этом запросе мы будем вызывать хранимый процесс sp_columns, и он ожидает некоторые параметры, как показано ниже:

exec sp_columns 'jdbc_function_escapes', null, null, null;

Эта команда вернет набор результатов с набором столбцов. В нашем примере мы сопоставим только два столбца с ответом, предоставленным сервисом.

Запрос для этого хранимого вызова proc можно увидеть ниже:

<query id="GetColumns" useConfig="Sybase">
    <sql>exec sp_columns ?, ?, ?, ?</sql>
    <result element="Columns" rowName="Column">
        <element column="column_name" name="ColumnName" xsdType="string"/>
        <element column="type_name" name="TypeName" xsdType="string"/>
    </result>
    <param name="table_name" optional="false" sqlType="STRING"/>
    <param defaultValue="#{NULL}" name="table_owner" optional="true" sqlType="STRING"/>
    <param defaultValue="#{NULL}" name="table_qualifier" optional="true" sqlType="STRING"/>
    <param defaultValue="#{NULL}" name="column_name" optional="true" sqlType="STRING"/>
</query>

В отличие от предыдущих примеров, у нас есть ожидаемые параметры, определенные с вопросительными знаками, поэтому эта процедура ожидает до 4 параметров. И мы сопоставляем значения с этими параметрами, используя узлы параметров. В нашем случае у нас есть 4 параметра.

Затем в нашем ресурсе мы определяем ресурс и параметры, которые ожидает ресурс:

<resource method="GET" path="/columns">
    <call-query href="GetColumns">
        <with-param name="table_name" query-param="table_name"/>
        <with-param name="table_owner" query-param="table_owner"/>
        <with-param name="table_qualifier" query-param="table_qualifier"/>
        <with-param name="column_name" query-param="column_name"/>
    </call-query>
</resource>

В этом примере мы определили ресурс / столбцы, и у нас определены некоторые параметры. В этом случае мы сопоставляем параметры, которые мы передадим при вызове ресурса, с параметрами, определенными в запросе. В этом примере мы используем одинаковые имена для параметров ресурса и запроса. Эти параметры в ресурсах будут переданы в виде строк запроса, как показано ниже:

http://localhost:8280/services/SybaseTest/columns?table_name=product
http://localhost:8280/services/SybaseTest/columns?table_name=product&column_name=price

Пример вывода можно увидеть ниже:

<?xml version="1.0" encoding="UTF-8"?>
<Columns xmlns="http://ws.wso2.org/dataservice">
    <Column>
        <ColumnName>ID</ColumnName>
        <TypeName>numeric identity</TypeName>
    </Column>
    <Column>
        <ColumnName>name</ColumnName>
        <TypeName>varchar</TypeName>
    </Column>
    <Column>
        <ColumnName>description</ColumnName>
        <TypeName>varchar</TypeName>
    </Column>
    <Column>
        <ColumnName>price</ColumnName>
        <TypeName>decimal</TypeName>
    </Column>
</Columns>

Это на сегодня. Теперь мы можем создавать WSO2 EI DataServices, использующие данные с серверов Sybase.

Увидимся в следующем посте 🙂

Дальнейшее чтение

Подключение к базе данных и транзакции в Python

Python ODBC Custom API