از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
ادغام H2 با Node.js و ExpressH2 یک سرور پایگاه داده سبک وزن است که به زبان جاوا نوشته شده است. می توان آن را در برنامه های جاوا جاسازی کرد یا به عنوان یک سرور مستقل اجرا کرد. در این آموزش، بررسی خواهیم کرد که چرا H2 می تواند گزینه خوبی برای پروژه های شما باشد. همچنین یاد خواهیم گرفت که چگونه H2 را با Node.js با ساختن یک…
سرفصلهای مطلب
معرفی
H2 یک سرور پایگاه داده سبک وزن است که به زبان جاوا نوشته شده است. می توان آن را در برنامه های جاوا جاسازی کرد یا به عنوان یک سرور مستقل اجرا کرد.
در این آموزش دلیل آن را بررسی می کنیم H2 می تواند گزینه خوبی برای پروژه های شما باشد. همچنین روش ادغام را یاد خواهیم گرفت H2 با Node.js با ساخت یک ساده بیان API.
ویژگی های H2
H2 با در نظر گرفتن عملکرد ساخته شده است.
“H2 ترکیبی از: سریع، پایدار، آسان برای استفاده، و ویژگی ها.
با اینکه H2 برجسته است، عمدتاً به این دلیل که می تواند در برنامه های جاوا جاسازی شود، ویژگی های جالبی دارد که در نسخه سرور آن نیز اعمال می شود. بیایید برخی از آنها را در ادامه ببینیم.
اندازه و عملکرد
این .شیشه فایل مورد استفاده برای نسخه سرور حدود 2 مگابایت است. ما میتوانیم آن را دانلود کنید از H2 سایت، همراه با اسکریپت ها و اسناد اضافی. اگر ما در Maven Central جستجو کنیم، می توانیم دانلود کنید .شیشه فایل روی خودش
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.
برنامه ما در پایان این آموزش به این صورت خواهد بود:
در سمت چپ نمودار، API Client را می بینیم. آن کلاینت می تواند تابع “امتحانش کن” باشد ویرایشگر Swagger، یا هر مشتری دیگری مانند Postman یا cURL.
در طرف دیگر ما پیدا می کنیم H2 سرور پایگاه داده در حال اجرا روی پورت TCP 5234
همانطور که در بالا توضیح داده شد.
در نهایت، برنامه ما در وسط از دو فایل تشکیل شده است. اولین مورد را خواهد داشت بیان برنامه ای که به تمام درخواست های REST API پاسخ می دهد. تمام نقاط پایانی که در تعریف بالا توضیح دادیم به این فایل اضافه خواهند شد.
فایل دوم دارای توابع ماندگاری برای دسترسی به پایگاه داده برای اجرای عملیات CRUD با استفاده از JDBC بسته بندی
طرحواره پایگاه داده
برای ذخیره منبع Exoplanet در یک H2 ابتدا باید توابع اصلی CRUD را بنویسیم. بیایید با ایجاد پایگاه داده شروع کنیم.
ما استفاده می کنیم JDBC بسته دسترسی به پایگاه داده از طریق JDBC:
const JDBC = require('jdbc');
const jinst = require('jdbc/lib/jinst');
if (!jinst.isJvmCreated()) {
jinst.addOption("-Xrs");
jinst.setupClasspath(('../h2-1.4.200.jar'));
}
let h2 = new JDBC({
url: 'jdbc:h2:tcp://localhost:5234/exoplanets;database_to_lower=true',
drivername: 'org.h2.Driver',
properties: {
user : 'SA',
password: ''
}
});
let 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)"
);
});
},
این initialize()
تابع به دلیل توابع کمکی که از قبل نوشته شده است به اندازه کافی ساده است. اگر جدول سیارات فراخورشیدی از قبل وجود نداشته باشد، میسازد. این تابع باید قبل از اینکه API ما شروع به دریافت درخواست کند، اجرا شود. بعداً خواهیم دید که کجا این کار را با Express انجام دهیم.
این h2
شی با رشته اتصال و اعتبار برای دسترسی به سرور پایگاه داده پیکربندی می شود. برای این مثال ساده تر است، اما در مورد امنیت جا برای بهبود وجود دارد. میتوانیم اعتبارنامههایمان را در جای دیگری ذخیره کنیم، مثلاً متغیرهای محیطی.
همچنین، ما نیاز به اضافه کردن مسیر به H2 فایل jar روی روش jinst.setupClasspath()
. این به این دلیل است که JDBC بسته برای اتصال به درایور نیاز دارد H2، org.h2.Driver
.
رشته اتصال JDBC به پایان می رسد /exoplanets;database_to_lower=true
. این بدان معنی است که هنگام اتصال برای اولین بار یک پایگاه داده تماس می گیرد exoplanets
ایجاد خواهد شد. همچنین نام جدول و ستون با حروف کوچک ذخیره می شود. این API را ساده می کند بنابراین نیازی به تبدیل نام اموال نخواهد بود.
این queryDB()
تابع از JDBC
روش های کتابخانه ای برای دسترسی به پایگاه داده اول، لازم است reserve()
اتصال به پایگاه داده مراحل بعدی عبارتند از createStatement()
و سپس executeQuery()
اگر نتیجه ای انتظار می رود، یا executeUpdate()
در غیر این صورت. اتصال همیشه آزاد می شود.
همه توابع بالا ممکن است یک خطا برگردانند. برای ساده کردن این مثال، تمام خطاها بدون علامت رها می شوند، اما روی یک پروژه واقعی ما باید آنها را بررسی کنیم.
این getH2()
تابع یک شی را برمی گرداند که پایگاه داده را نشان می دهد. با استفاده از مکانیزم مشابهی که کلاس های Singleton برای برگرداندن همیشه فقط یک نمونه استفاده می کنند، آن شی را فقط یک بار ایجاد می کند.
بیایید اکنون داده های کاربر را تأیید کنیم و به آنها اجازه دهیم عملیات CRUD را انجام دهند.
توابع پایگاه داده CRUD
بیایید توابع مورد نیاز را ایجاد کنیم تا این برنامه بتواند عملیات CRUD را انجام دهد روی سیارات فراخورشیدی ما آنها را به آنها اضافه می کنیم module.exports
تا بتوانیم آنها را از فایل های دیگر به راحتی ارجاع دهیم و a persistence.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}`));
},
};
هر دو get()
و getAll()
توابع از پایگاه داده برای برگرداندن یک یا چند سیاره فراخورشیدی پرس و جو می کنند. API آنها را مستقیماً به مشتری API برمی گرداند.
همه توابع عمدتاً پرس و جوهای SQL هستند، اما create()
و update()
سزاوار توضیح بیشتر است
این INSERT
دستور SQL می تواند ستون و مقادیر جدا شده را در فرم دریافت کند INSERT INTO table (column1Name) VALUES ('column1Value')
. ما می توانیم استفاده کنیم join()
روشی برای ایجاد یک رشته از ستونهایی که با کاما از هم جدا شدهاند، و کاری مشابه برای پیوستن به تمام مقادیری که میخواهیم در create()
تابع.
این UPDATE
دستور SQL کمی پیچیده تر است. شکل آن است UPDATE table SET column1Name = 'column1Value'
. بنابراین باید یک آرایه جدید در آن ایجاد کنیم update()
تابع برای ذخیره مقادیر در این فرمت و join()
آنها بعدا
بیایید تمام توابع پایگاه داده را ذخیره کنیم روی فایل خودش persistence.js
، بنابراین می توانیم هنگام فراخوانی توابع موجود در فایل API مقداری زمینه اضافه کنیم، مانند این:
const persistence = require('./persistence');
persistence.getAll();
طرحواره جوی
به عنوان یک قاعده کلی، ما همیشه باید آنچه را که کاربر ارسال می کند قبل از استفاده از آن اعتبارسنجی کنیم، برای مثال زمانی که کاربر تلاش می کند یک منبع ایجاد کند.
برخی از بسته ها این کار را آسان می کنند. استفاده خواهیم کرد جوی برای انجام اعتبار سنجی
ابتدا باید طرحی از منبع خود، تعریفی از خواص و انواع آنها تعریف کنیم. ما را به یاد SQL می اندازد CREATE
عبارتی که قبلا تعریف کردیم:
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()
});
const options = { stripUnknown: true };
// Inupt to validate
let input = { /*...*/ };
const { value } = exoplanetSchema.validate(input, options);
هر نوع اعتبار بخشی را اعمال می کند. به عنوان مثال link
ملک باید شبیه a باشد URI، و name
است required()
.
بعداً میتوانیم یک منبع را با استفاده از آن تأیید کنیم exoplanetSchema.validate(input, options)
روش. این متد یک شی را با یک باز می گرداند error
ویژگی با خطاهای اعتبارسنجی در صورت وجود، و a value
ویژگی با شی پردازش شده ما از این اعتبار سنجی هنگام ایجاد و به روز رسانی یک شی استفاده خواهیم کرد.
برای افزودن استحکام به API خود، بهتر است هر ویژگی اضافی که در طرح ما گنجانده نشده است را نادیده بگیریم و دور بریزیم. این در تعریف بالا با تنظیم به دست می آید stripUnknown
گزینه ای به true
.
REST API با Express
ما از بسته Express برای ایجاد REST 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 خود استفاده کنیم. اگر مایلید درباره Handling CORS با Node.js و Express بیشتر بخوانید، ما شما را تحت پوشش قرار داده ایم.
دوم، ما اضافه می کنیم express.json()
میان افزار برای فعال کردن تجزیه اشیاء JSON در بدنه درخواست ها.
بیایید اکنون چند نقطه پایانی به API اضافه کنیم. ما با شروع post()
و put()
، همانطور که از آن استفاده می کنند جوی اعتبار سنجی توضیح داده شده در بخش آخر:
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 پشتیبانی می کند، بنابراین در این مورد، ما داریم post()
و put()
به عنوان دو عملکرد
در هر دو تابع، منبع ابتدا اعتبار سنجی می شود و هر کدام error
به مشتری API برگردانده می شود. برای ساده نگه داشتن این کد، تنها اولین خطای اعتبارسنجی در آن صورت برگردانده می شود.
put()
همچنین با تلاش برای دریافت آن از پایگاه داده، وجود منبع را بررسی می کند. این منبع را فقط در صورت وجود به روز می کند.
با post()
و put()
توابعی که نیاز به اعتبار سنجی دارند، بیایید به آنها رسیدگی کنیم get()
روشهایی که کاربران میخواهند به سیارات فراخورشیدی و همچنین سیارههای فراخورشیدی نگاهی بیندازند delete()
تابع مورد استفاده برای حذف یک سیاره فراخورشیدی از پایگاه داده:
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");
});
هنگام راهاندازی سرور، تماس برگشتی بالا فقط یک بار فراخوانی میشود، بنابراین مکان مناسبی برای آن است initialize()
پایگاه داده.
نتیجه
H2 یک سرور پایگاه داده مفید، کارآمد و آسان برای استفاده است. اگرچه این یک بسته جاوا است، اما به عنوان یک سرور مستقل نیز اجرا می شود، بنابراین می توانیم از آن در Node.js با JDBC بسته بندی
در این آموزش ابتدا یک CRUD ساده تعریف کردیم تا روش دسترسی به پایگاه داده و اینکه کدام توابع در دسترس هستند را نشان دهیم. پس از آن یک REST API با آن تعریف کردیم بیان. این به ما کمک کرد تا ایده کامل تری داشته باشیم روی روش دریافت منابع و ذخیره آنها H2.
اگرچه چندین مفهوم به دلیل اختصار حذف شده است، مانند احراز هویت و صفحه بندی، این آموزش مرجع خوبی برای شروع استفاده است. H2 در ما بیان پروژه ها.
(برچسبها برای ترجمه)# جاوا اسکریپت
منتشر شده در 1403-01-20 06:49:03