Автор оригинала: Leandro Cofre.
Вступление
H2 Это легкий сервер базы данных, написанный в Java. Он может быть встроен в приложения Java или выполняется в качестве автономного сервера.
В этом руководстве мы рассмотрим, почему H2 Может быть хорошим вариантом для ваших проектов. Мы также узнаем, как интегрировать H2 С Node.js, создавая простой Экспресс API.
Особенности H2
H2 был построен с учетом производительности.
« H2 – это комбинация: быстрая, стабильная, простая в использовании и функциях».
Хотя H2 Заметно в основном потому, что он может быть встроен в приложения Java, у него есть некоторые интересные функции, которые также относятся к его версии сервера. Давайте посмотрим некоторые из них следующие.
Размер и производительность
.jar Файл, используемый для версии сервера, составляет около 2 МБ. Мы можем Скачайте его из H2 сайт , в комплекте с дополнительными сценариями и документацией. Если мы ищем в Maven Central, мы можем Скачать .jar файл самостоятельно Отказ
H2 Производительность сияет в его встроенной версии. Даже так, Официальный ориентир показывает, что его версия клиент-сервер также впечатляет.
Базы данных и шифрования в памяти
Базы данных в памяти не являются постоянными. Все данные хранятся в памяти, поэтому скорость значительно увеличивается.
H2 Сайт объясняет, что базы данных в памяти особенно полезны при прототипировании или при использовании баз данных только для чтения.
Шифрование – еще одна полезная функция для защиты данных в покое. Базы данных могут быть зашифрованы с помощью AES-128 алгоритм.
Другие полезные особенности
H2 Также предоставляет режим кластера, возможность запуска нескольких серверов и соединять их вместе. Пишетки выполняются во всех серверах одновременно, а чтение сделано с первого сервера в кластере.
H2 сюрпризы для его простоты. Он обеспечивает несколько полезных функций, и его легко настроить.
Давайте начнем H2 Сервер при подготовке к следующим разделам:
$ java -cp ./h2-1.4.200.jar org.h2.tools.Server -tcp -tcpAllowOthers -tcpPort 5234 -baseDir ./ -ifNotExists
Аргументы, которые начинаются с TCP
Включить связь с сервером. ifnotexists
Аргумент позволяет создавать базу данных при доступе к ней в первый раз.
Описание API и общей диаграммы
Предположим, мы пишем API для регистрации всех экзопланет, найденных на сегодняшний день. Экзопланеты – это планеты за пределами нашей солнечной системы, орбиты других звезд.
Это наш простой API определение , Crud для одного ресурса:
Это определение вместе с остальной частью кода мы увидим следующее доступно в этом Github Repo Отказ
Вот как наше приложение будет выглядеть в конце этого руководства:
Слева от диаграммы мы видим клиент API. Этот клиент может быть «попробовать его» функцию Редактор Swagger или любой другой клиент, как Postman или Curl.
На другом конце мы находим H2 Сервер базы данных, работает на порт TCP 5234
Как объяснено выше.
Наконец, наше приложение в середине состоит из двух файлов. Первый будет иметь Экспресс Приложение, которое ответит на все запросы API для отдыха. Все конечные точки, которые мы описали в определении выше, будут добавлены в этот файл.
Второй файл будет иметь постоянство, функции для доступа к базе данных для выполнения операций CRUD, используя JDBC упаковка.
Схема базы данных
Чтобы сохранить ресурс Exoplanet для H2 База данных Мы должны сначала написать основные функции Crud. Давайте начнем с создания базы данных.
Мы используем JDBC Пакет для доступа к базам данных через JDBC:
var JDBC = require('jdbc'); var jinst = require('jdbc/lib/jinst'); if (!jinst.isJvmCreated()) { jinst.addOption("-Xrs"); jinst.setupClasspath(['../h2-1.4.200.jar']); } var h2 = new JDBC({ url: 'jdbc:h2:tcp://localhost:5234/exoplanets;database_to_lower=true', drivername: 'org.h2.Driver', properties: { user : 'SA', password: '' } }); var h2Init = false; function getH2(callback) { if (!h2Init) h2.initialize((err) => { h2Init = true; callback(err) }); return callback(null); }; function queryDB(sql, callback) { h2.reserve((err, connobj) => { connobj.conn.createStatement((err, statement) => { if(callback) { statement.executeQuery(sql, (err, result) => h2.release(connobj, (err) => callback(result))); } else { statement.executeUpdate(sql, (err) => h2.release(connobj, (err) => { if(err) console.log(err) })); } }); }); }; module.exports = { initialize: function(callback) { getH2((err) => { queryDB("CREATE TABLE IF NOT EXISTS exoplanets (" + " id INT PRIMARY KEY AUTO_INCREMENT," + " name VARCHAR NOT NULL," + " year_discovered SIGNED," + " light_years FLOAT," + " mass FLOAT," + " link VARCHAR)" ); }); },
Инициализировать ()
Функция достаточно проста из-за функций помощника, написанного заранее. Это создает таблицу экзопланетов, если она уже не существует. Эта функция должна быть выполнена до того, как наш API запускает прием запросов. Позже мы увидим, где это сделать с Express.
H2
Объект устанавливается с помощью строки подключения и учетных данных для доступа к серверу базы данных. Это проще для этого примера, но есть комната для улучшения в отношении безопасности. Мы могли бы сохранить наши полномочия в другом месте, например, для среды для переменных.
Кроме того, нам нужно было добавить путь к H2 JAR файл по методу jinst.setupclasspath ()
Отказ Это потому, что JDBC Пакет нуждается водителя для подключения к H2 , org.h2.driver
Отказ
Строка подключения JDBC заканчивается exoplanets; database_to_lower = true
Отказ Это означает, что при подключении к первому времени база данных называется Экзопланеты
будет создан. Также имена таблицы и столбцов будут сохранены в нижнем регистре. Это упростит API, чтобы преобразование имени свойств не потребуется.
QueryDB ()
Функция использует JDBC
Методы библиотеки для доступа к базе данных. Во-первых, это нужно Забронировать ()
связь с базой данных. Следующие шаги – CreateStatement ()
а потом executewhery ()
Если результат ожидается, или ExecuteUpdate ()
иначе. Соединение всегда выпущено.
Все функции выше могут вернуть ошибку. Чтобы упростить этот пример, все ошибки остаются незаменимыми, но на реальном проекте мы должны их проверить.
geth2 ()
Функция Возвращает объект, который представляет базу данных. Это создаст этот объект только один раз, используя тот же механизм классов Singleton, используемый для возврата только один экземпляр всегда.
Давайте теперь проверяем пользовательские данные и позвольте им выполнять операции CRUD.
Функции базы данных Crud
Давайте сделаем необходимые функции, чтобы позволить этому приложению выполнять операции CRUD на экзопланетах. Мы добавим их в Module.exports
Так что мы можем легко получить их из других файлов и создать Персистентность.js
Модуль помощника, который мы можем использовать:
module.exports = { getAll: function(callback) { getH2((err) => queryDB("SELECT * FROM exoplanets", (result) => { result.toObjArray((err, results) => callback(results)) })); }, get: function(id, callback) { getH2((err) => queryDB(`SELECT * FROM exoplanets WHERE id = ${id}`, (result) => { result.toObjArray((err, results) => { return (results.length > 0) ? callback(results[0]) : callback(null); }) })); }, create: function(exoplanet) { getH2((err) => { columns = Object.keys(exoplanet).join(); Object.keys(exoplanet).forEach((key) => exoplanet[key] = `'${exoplanet[key]}'`); values = Object.values(exoplanet).join(); queryDB(`INSERT INTO exoplanets (${columns}) VALUES(${values})`); }); }, update: function(id, exoplanet) { getH2((err) => { keyValues = [] Object.keys(exoplanet).forEach((key) => keyValues.push(`${key} = '${exoplanet[key]}'`)); queryDB(`UPDATE exoplanets SET ${keyValues.join()} WHERE id = ${id}`); }); }, delete: function(id) { getH2((err) => queryDB(`DELETE FROM exoplanets WHERE id = ${id}`)); }, };
Оба Получить ()
и getall ()
Функции Запрос базы данных для возврата одного или нескольких экзопланет. API вернет их непосредственно в клиент API.
Все функции в основном SQL-запросы, но Создать ()
и Обновление ()
заслуживают большего объяснения.
Вставить
Заявление SQL может принимать столбец и разделенные значения, в форме Вставьте в таблицу (столбец1name) Значения («COLON1VALUE»)
Отказ Мы можем использовать Присоединяйтесь ()
Способ генерирования одной строки столбцов, разделенных запятыми, и сделать что-то подобное для присоединения всех значений, которые мы хотим в Создать ()
функция.
Обновить
Заявление SQL немного сложнее. Его форма – Обновление таблицы набор
Отказ Поэтому нам нужно создать новый массив в Обновление ()
Функция для хранения значений в этом формате и Присоединяйтесь ()
их позже.
Давайте сохраним все функции базы данных в своем собственном файле, Персистентность.js
Таким образом, мы можем добавить некоторое контекст, когда мы вызываем функции в файле API, как это:
const persistence = require('./persistence'); persistence.getAll();
Joi Schema
Как правило, мы всегда должны подтвердить, что отправляет пользователь перед его использованием, например, когда пользователь пытается создать ресурс.
Некоторые пакеты облегчают эту задачу. Мы будем использовать Джой достичь валидации.
Во-первых, нам нужно определить схему нашего ресурса, определение свойств и их типов. Это напоминает нам о SQL Создать
Заявление Мы определены ранее:
const Joi = require('joi'); const exoplanetSchema = Joi.object({ id: Joi.number(), name: Joi.string().required(), year_discovered: Joi.number(), light_years: Joi.number(), mass: Joi.number(), link: Joi.string().uri() }) options({ stripUnknown: true });
Каждый тип обеспечит некоторую проверку. Например, ссылка
Собственность должна выглядеть как Uri и Имя
это Требуется ()
Отказ
Позже мы можем проверить ресурс, используя exoplanetschema.validate (feobject)
метод. Этот метод вернет объект с Ошибка
. Недвижимость с ошибками валидации, если были какие-либо, а ценность
Собственность с обработанным объектом. Мы будем использовать эту проверку при создании и обновлении объекта.
Чтобы добавить надежность нашего API, было бы неплохо проигнорировать и отменить любую дополнительную недвижимость, не включенную в нашу схему. Это достигается в определении выше, установив stripunknown
Вариант для правда
Отказ
API отдыха с Express
Мы будем использовать Express Package для создания нашего API для отдыха. И как мы только что видели, мы также будем использовать Джой проверять ресурсы.
Давайте настроим регулярный экспресс-сервер:
const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors()); app.use(express.json());
Переменная приложения – наша API, пуста на данный момент. Express позволяет расширять его функциональность благодаря использованию промежуточного программного обеспечения, функций, которые могут изменять запросы и ответы нашего API. В этом случае мы используем два подразготения.
Во-первых, CORS ()
позволит другим приложениям браузера позвонить нашему API. Это включает в себя Редактор Swagger Мы можем использовать для проверки нашего API позже. Если вы хотите прочитать больше о Обработка CORS с Node.js и Express Мы охватываем вас.
Во-вторых, мы добавляем Express.json ()
промежуточное программное обеспечение для разбора объектов JSON в теле запросов.
Теперь добавим несколько конечных точек на API. Мы начнем с пост ()
и поставить ()
, как они используют Джой Валидация объяснена в последнем разделе:
app.post('/exoplanets', (req, res) => { delete req.body.id; const { error, value } = exoplanetSchema.validate(req.body); if(error) res.status(405).send(error.details[0].message); persistence.create(value); res.status(201); }); app.put('/exoplanets/:id', (req, res) => { delete req.body.id; const { error, value } = exoplanetSchema.validate(req.body); if(error) { res.status(405).send(error.details[0].message); } persistence.get(req.params.id, (result) => { if(result) { persistence.update(req.params.id, value); res.status(201); } else { res.status(404); } }); });
Express поддерживает одну функцию на http глагол, поэтому в этом случае мы имеем пост ()
и поставить ()
как две функции.
В обеих функциях ресурс подтверждается первым, и любой Ошибка
. возвращается в клиент API. Чтобы сохранить этот код просто, только в этом случае возвращается только первая ошибка проверки.
поставить ()
Также проверяет, существует ли ресурс, пытаясь получить его из базы данных. Он обновит ресурс только в том случае, если он существует.
С пост ()
и поставить ()
Функции, которые требуют проверки, давайте обрабатываем Получить ()
Методы, когда пользователи хотели бы взглянуть на экзопланеты, а также Удалить ()
Функция, используемая для удаления экзопланета из базы данных:
app.get('/exoplanets', (req, res) => persistence.getAll((result) => res.send(result))); app.get('/exoplanets/:id', (req, res) => { persistence.get(req.params.id, (result) => { if(result) res.send(result); else res.status(404); }); }); app.delete('/exoplanets/:id', (req, res) => { persistence.get(req.params.id, (result) => { if(result) { persistence.delete(req.params.id); res; } else { res.status(404); } }); });
Определение всех конечных точек, давайте настроим порт, на котором приложение будет прослушивать запросы на:
app.listen(5000, () => { persistence.initialize(); console.log("Exoplanets API listening at http://localhost:5000") });
Вышеуказанный вызов будет вызываться только один раз при запуске сервера, так что это идеальное место для Инициализировать ()
база данных.
Заключение
H2 Это полезный сервер базы данных, исполнительные и простые в использовании. Хотя это пакет Java, он также работает как автономный сервер, поэтому мы можем использовать его в Node.js с JDBC упаковка.
В этом руководстве мы определили сначала простой Crud, чтобы проиллюстрировать, как получить доступ к базе данных, и какие функции доступны. После этого мы определили API отдыха с Экспресс Отказ Это помогло нам иметь более полную идею о том, как получать ресурсы и сохранить их на H2 Отказ
Хотя несколько концепций были опущены ради краткости, как аутентификация и пейджинг, этот учебник является хорошим ссылкой на начало использования H2 в нашем Экспресс проекты.