Pull to refresh
0
SAP
Лидер рынка корпоративных приложений

SAP HANA Cloud Platform: загрузка и хранение данных

Reading time7 min
Views12K
В предыдущей статье мы рассказали о том, как создать тестовый экземпляр облачной платформы (далее HCP — HANA Cloud Platform) и как связать среду разработки Eclipse с облаком на примере простейшего XS приложения (XS — eXtended Services).

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

Итак, что мы имеем. Первое — доступ к панели управления нашего облака по адресу https://account.hanatrial.ondemand.com/cockpit

Второе — созданный экземпляр платформы на SAP HANA под названием helloworldtrial.
image

Третье — установленную среду разработки Eclipse с плагином для SAP HANA Cloud и с созданным подключением к helloworldtrial:
image

Что мы хотим сделать: создать таблицу в базе данных SAP HANA и загрузить туда данные из внешнего источника. Для наших целей будем хранить информацию о текущей температуре воздуха в нескольких городах. Данные, для примера, будем брать с openweathermap.org.

Начнём с создания нового проекта. Запускаем наш Eclipse, открываем перспективу SAP HANA Development (Window > Open Perspective > Other...):
image

Создаём новый проект XS приложения, указав его название (File > New > Project… > SAP HANA Cloud):
image

Далее нам требуется выполнить стандартные шаги по выбору workspace’а и пакета. Внимание! Для нашего примера важно выбрать пакет, соответствующий нашему экземпляру облачной системы, вида pXXXXXXXXtrial.helloworldtrial. Где pXXXXXXXXtrial — имя пользователя в облачной системе:
image

И укажем наш главный файл со скриптом, который и будет выполнять всю работу — get_weather.xsjs:
image

Контроль доступа к пакету. Файл .xsaccess
С помощью файла .xsaccess мы указываем свойства нашего XS приложения (например, требуемая авторизация для исполнения скрипта и т.д.). Заменим содержимое этого файла на:
{
     "exposed" : true,
     "default_file" : "get_weather.xsjs"
}

Свойство exposed показывает, что данное XS приложение может быть выполнено на сервере из URL. Свойство default_file указывает главный исполняемый файл приложения; это позволит нам запустить его напрямую из панели управления (cockpit), не дописывая имя файла.

Теперь активируем наше приложение для проверки того, что на данном этапе все шаги были выполнены правильно. Для этого щёлкнем правой кнопкой мыши на нашем проекте во вкладке Project Explorer и в контекстном меню выберем Team > Activate.

Перезапустим панель управления в веб браузере нажав обновить (F5); иначе наше XS приложение не отображается в списке:
image

Щёлкнем на URL нашего XS приложения:
image

Должно открыться новое окно с содержимым “Wrong content type request use application/json”. Удостоверившись, что наша заготовка запускается, мы можем двигаться дальше.

Создание таблицы в базе данных
Создадим таблицу в базе данных, которая будет содержать столбцы: дата и время, наименование населённого пункта и текущую температуру воздуха.
Есть несколько способов создать таблицу в системе — с помощью интерактивного дизайнера, SQL скрипта или .hdbtable файла.

Самый быстрый способ — запустить на выполнение скрипт, подставив имя нашей схемы. Идём на вкладку Systems и запускаем SQL консоль для нашего облака:
image

Запускаем такой скрипт, подставив имя нашей схемы NEO_:
create column table "NEO_<<<>>>"."T_WEATHER"(
    "ID" INTEGER GENERATED ALWAYS AS IDENTITY (MINVALUE 0 START WITH 0 INCREMENT BY 1),
    "FORECAST_TMSTMP" TIMESTAMP NOT NULL ,
    "LOCATION"        NVARCHAR(50) NOT NULL,
    "TEMPERATURE"     REAL NOT NULL,
    "TIMESTMP"        TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    PRIMARY KEY ("ID"));

Обратим внимание на то, что мы создаём таблицу с колоночным хранением. А также неявно создаём т.н. sequence, который генерирует последовательность целых чисел и, при создании записей в таблице, сохраняет их в атрибуте ID.

Обновив каталог NEO_, увидим нашу таблицу:
image

Роль пользователя БД. Файл .hdbrole
В бесплатной trial системе у пользователя есть весьма ограниченный набор прав. Это касается, в частности, авторизации на изменение объектов в каталоге и управления пользовательскими аккаунтами. Поэтому в trial системе есть набор процедур в схеме “HCP”, которые позволяют пользователю управлять правами на созданные им объекты.

Для записи и чтения данных таблицы T_WEATHER нам потребуется новая роль. Добавим файл типа .hdbrole в наш проект (в главном меню File > New > Other…):
image

назовём его weather_access:
image

Заменим содержимое этого файла на следующий фрагмент, а затем активируем файл:
role p<<<>>>trial.helloworldtrial.TryWeather::weather_access {
catalog sql object "NEO_<<<>>>>"."T_WEATHER": SELECT, UPDATE, INSERT;
}

Заменим p<<<>>>trial на имя вашего пользователя. Вместо схемы NEO_<<<>>>> необходимо вставить наименование своей схемы, которую мы сохранили при создании таблицы. А теперь начинается магия, связанная с тем, что наше облако в триал режиме создаёт множество пользователей на одной системе. И для разделения прав доступа у этих пользователей весьма ограниченные привилегии.

Для того чтобы наш системный пользователь получил роль weather_access, мы должны выполнить системную процедуру.
Запустим SQL консоль и в ней выполним такой скрипт:
call "HCP"."HCP_GRANT_ROLE_TO_USER"('p<<<>>>trial .helloworldtrial.TryWeather::weather_access', 'p<<<>>>');

Дополнительные встроенные процедуры в trial системе
Хотелось бы обратить внимание на то, что при изменении таблиц, представлений, процедур в каталоге trial системы необходимо в явном виде обновлять разрешения на доступ к этим объектам. Это делается вызовом процедуры:
call "HCP"."HCP_GRANT_SELECT_ON_ACTIVATED_OBJECTS";

После изменения и активации файла .hdbrole необходимо выполнить:
call "HCP"."HCP_GRANT_ACTIVATED_ROLES";


Основной скрипт. Файл .xsjs
Итак, у нас есть заготовка XS скрипта и таблица в базе данных, для которой мы добавили разрешение на запись и чтение данных. В эту таблицу мы будем записывать данные о текущей погоде.
Откуда можно получать данные о погоде
Для получения температуры мы используем API от openweathermap.org. Подробнее данный сервис был описан в статье на Хабре.
Пример URL для получения текущих данных о погоде в Москве: http://api.openweathermap.org/data/2.5/weather?q=Moscow,ru&units=metric.
Полученные данные в виде JSON объекта содержат, в том числе, информацию о температуре воздуха в формате unix timestamp. Тэг “dt”:
{
	...
	"dt " : 1430318471,
	"id " : 524901,
	"name " : "Moscow ",
	"cod " : 200
}


Мы извлечём данные о погоде и запишем их в таблицу.
Исходный код скрипта
Важно! Замените значения констант в первых двух строках на ваш логин (заканчивается на -trial) и наименование схемы базы данных NEO_:
image

var CONST_ROOT_PACKAGE = "<<<pXXXXXtrial>>>";
var CONST_NEO_SCHEMA = "<<<NEO_XXXXXXXXXXXXXXXX>>>";

function getCurrentWeather(city_name) {
	var destination_package = "helloworldtrial.TryWeather";
	var destination_name = "o_weather";

	var destPackagePath = CONST_ROOT_PACKAGE + "." + destination_package;
	var dest = $.net.http.readDestination(destPackagePath, destination_name);

	var client = new $.net.http.Client();
	var req = new $.web.WebRequest($.net.http.GET, "?q=" + city_name
			+ "&units=metric");
	client.request(req, dest);
	var response = client.getResponse();

	var weather_data = JSON.parse(response.body.asString(),
			function(key, value) {
				if (key === "dt") {
					return new Date(value * 1000);
				}
				return value;
			});
	return [ weather_data.dt, city_name, weather_data.main.temp ];
}

function storeData(data_receiving_time, city, temp) {

	var conn = $.db.getConnection();
	var stmt = conn
			.prepareStatement("INSERT INTO \""
					+ CONST_NEO_SCHEMA
					+ "\".T_WEATHER (FORECAST_TMSTMP,LOCATION,TEMPERATURE) VALUES (?,?,?)");

	stmt.setTimestamp(1, data_receiving_time);// время получения данных о погоде OpenWeatherMap
	stmt.setString(2, city);
	stmt.setFloat(3, temp);

	var rs = stmt.executeQuery();

	rs.close();
	stmt.close();
	conn.commit();
	conn.close();

}

function processRequest() {
	var cityNames = [ "Moscow,ru", "Saint Petersburg,ru", "Novosibirsk,ru",
			"Volgograd,ru", "Krasnoyarsk,ru" ];
	var body = "";
	var cityName, i;
	var dt;
	var city;
	var temp;
	var out_vals;

	try {
		for (i = 0; i < cityNames.length; i++) {
			cityName = cityNames[i];
			out_vals = getCurrentWeather(cityName);
			dt = out_vals[0];
			city = out_vals[1];
			temp = out_vals[2];

			storeData(dt, city, temp);
			body += "Данные сохранены.\nДата: " + dt + "\nГород: " + city
					+ "\nТемпература: " + temp + " C\n\n";

		}
		$.response.setBody(body);
		$.response.contentType = "text/plain";
		$.response.status = $.net.http.OK;

	} catch (e) {
		$.response.contentType = "text/plain";
		$.response.status = $.net.http.INTERNAL_SERVER_ERROR;
		$.response.setBody(e.toString());
	}
}

processRequest();


Данный код использует т.н. destination для вызова внешнего API.
А доступ к базе данных из Javascript осуществляется через объект соединения в пространстве имён $.db:
var conn = $.db.getConnection();
var stmt = conn.prepareStatement("INSERT INTO <<table>> (FORECAST_TMSTMP,LOCATION,TEMPERATURE) VALUES (?,?,?)");


Доступ к внешнему URL. Файл .xshttpdest
Добавим новый объект типа .xshttpdest с названием o_weather в наш проект:
image

И заменим содержимое этого файла на:
host = "api.openweathermap.org";
port = 80;
description = "current weather";
useSSL = false;
pathPrefix = "/data/2.5/weather";
authType = none;
useProxy = true;
proxyHost = "proxy-trial";
proxyPort = 8080;
timeout = 5000; // in milliseconds

Сохраним и активируем этот объект.

Теперь в панели управления HCP на вкладке с XS приложениями мы увидим новый элемент в панели Destinations:
image

Кликнув на URL нашего приложения, запустим скрипт и получим приблизительно такой результат на экране:
image

Теперь в Eclipse проверим, что данные были сохранены в таблице. Для этого по правой кнопке мыши на таблице T_WEATHER выберем Open Data Preview:
image

И убедимся, что новая запись в базе данных была создана:
image

Итого
Итак, в данной статье мы создали XS приложение, которое умеет получать данные из внешнего источника (в нашем случае — веб сервис) и сохранять их в таблице в базе данных HANA. Кроме того, мы создали два специальных объекта: определение ролей (weather_access.hdbrole) и определение канала для доступа к внешнему веб-сервису (o_weather.xshttpdest). А также вызвали хранимые процедуры для того, чтобы в trial системе дать разрешения на доступ к таблице базы данных.
Tags:
Hubs:
Total votes 8: ↑8 and ↓0+8
Comments8

Articles

Information

Website
sap.com
Registered
Founded
Employees
5,001–10,000 employees
Location
Германия