مدتی میشه که شروع کردم به یادگیری زبان جاوا چرا که این زبان، علیرغم این که زبان قشنگ و پرکاربردیه، کمک میکنه برنامهنویس بهتری هم بشم. گذشته از اون، مفاهیم شیءگرایی در جاوا به خوبی پیاده شدند و میشه تا حد زیادی هم برنامهنویسی و طراحی شیگرا رو با این زبان یاد گرفت.
خلاصه این که در ساعات بیکاری، دموی رایگان آموزش جاوای مشفق همدانی عزیز (وبسایت) رو دیدم و کمی هم در مورد جاوا و فرمورکهاش و …، تحقیق کردم. خلاصه که خواستم یه پروژه فان بزنم و نتیجتا تصمیم گرفتم کمی پروژه رو چالشی کنم. به همین خاطر تصمیم گرفتم که از دیتابیس در پروژه استفاده کنم. رسیدن به این نتیجه که الان در قالب آموزش برای شما درآمده، کار سادهای نبود ولی خب ارزشش رو داشت.
اسکولایت (SQLite) چیه؟
اسکولایت یک سیستم مدیریت پایگاهداده رابطهایه که در سال ۲۰۰۰ توسط ریچارد هیپ ساخته شده. این RDBMS عزیز، برخلاف نمونههای بزرگ و معروفی مثل MySQL, PostgresSQL, SQL Server و … که نیازمند یک سرور جداگانه هستند، نیازی به داشتن سرور نداره و همه چیز رو در یک فایل، عموما با پسوند sqlite یا sqlite3 ذخیره میکنه و اطلاعاتی مثل روابط و دادهها رو روی اون فایل مینویسه.
این نوع مدیریت دیتابیس برای نرمافزارهایی که نیاز دارند داده رو به صورت محلی ذخیره کنند و همچنین سرویسهای آنلاین کوچک که کاربر زیادی ندارند کاربردیه. همچنین میتونه برای ذخیره موقت اطلاعات هم استفاده بشه. به همین خاطر، محبوبیت زیادی کسب کرده. گذشته از این، در بسیاری از چارچوبها مانند جنگو یا ریلز، در محیط آزمایش (test) و توسعه (development) معموله که از SQLite استفاده کنند تا صرفا ببینن که آیا ساختار دادههاشون درسته یا خیر.
تعریف پروژه
خب، حالا که میدونیم قراره از جاوا و SQLite استفاده کنیم، بیایم پروژه رو تعریف کنیم. پروژه برای من به این شکل تعریف شده بود:
برنامهای بنویسید که یک نام و یک شماره تلفن از کاربر دریافت کرده و سپس آن را در یک پایگاهداده SQLite ذخیره کند.
برای این که پروژه رو کمی متفاوت از چیزی که خودم برای تمرین زدم کنیم، صورتش رو به این شکل تغییر میدیم :
برنامهای بنویسید که یک نام، شماره تلفن و ایمیل از کاربر دریافت کرده و سپس آن را در یک پایگاهداده SQLite ذخیره کند.
ابزارهای مورد استفاده در این پروژه
در این پروژه، من از این ابزارها استفاده کردم:
- جاوا نسخه ۱۳
- محیط یکپارچه توسعه IntelliJ IDEA
- درایور SQLite برای جاوا (لینک)
ضمنا، من از سیستمعامل لینوکس (در حال حاضر اوبونتو/دبیان) استفاده میکنم و چیزایی که در این آموزش بهشون اشاره میکنم عموما دستورات لینوکسی هستند. اگر ویندوزی هستید هم میتونید از WSL استفاده کنید یا دستورات مشابه پیدا کنید.
آمادهسازی و ایجاد پروژه
پس از باز کردن IntelliJ IDEA و سپس ایجاد یک پروژه Command Line جدید، از منوی File و زیرمنوی Project Structure زبانه Dependencies را انتخاب کرده و سپس فایل jar ای که برای SQLite JDBC Driver دریافت کردهاید را به پروژه وارد کنید. همچنین، من با دستور زیر، یک دیتابیس خالی در پوشهای در کامپیوتر خودم ایجاد کردم:
touch /home/prp-e/playground/java.sqlite3
به این شکل، من یک فایل قابل فهم برای SQLite ساختهام. قدم بعدی، آشنایی نسبی با پرسوجوهای SQLite است.
کمی آشنایی با SQLite
مثل هر دیتابیس SQL دیگری، SQLite هم مجموعهای از پرسوجوها اجرا میکنه تا به نتیجهای که ما میخوایم برسه. در این بخش، اونهایی که در پروژه استفاده میشن رو بررسی میکنیم.
ساخت جدول جدید
همونطور که اول گفتیم، قراره در جدول تماسهامون، نام، تلفن و ایمیل اشخاص رو ذخیره کنیم. به همین خاطر موارد رو لحاظ میکنیم:
- یک شناسه منحصر به فرد برای هرفرد که به صورت خودکار، افزایش پیدا کنه
- اسم فرد به صورت یک رشته متنی
- شماره فرد به صورت رشته متنی (برای شماره هایی که – یا + و … دارند)
- ایمیل فرد به صورت رشته متنی
پس پرسوجوی اول ما به این شکل میشه :
CREATE TABLE IF NOT EXISTS contacts(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, number TEXT NOT NULL, email TEXT NOT NULL);
در این پرسوجو، داریم میگیم که اگر جدولی به اسم contacts نبود بسازش. برای هر کاربر یک شناسه به صورت PRIMARY_KEY یا همون شناسه اولیه/منحصر به فرد درنظر بگیر که به صورت خودکار افزایش پیدا کنه. اسم، شماره و ایمیل هم به صورت متن دریافت کن اما خالی نباشن.
اضافه کردن تماس جدید
برای اضافه کردن تماس جدید، کل کاری که باید انجام بدیم اجرای این پرس و جوئه :
INSERT INTO contacts (name, number, email) VALUES ("John Doe", "1-555-123456", "john.doe@gmail.com");
در این پرس و جو میگیم که یک تماس جدید با مشخصات شخصی به نام John Doe به این پایگاه داده اضافه بشه.
پیادهسازی در جاوا
برای پیادهسازی پروژه، ما نیاز به این موارد داریم:
- تابعی که اسم دیتابیس، پرسوجوی اولیه و پرسوجوی مورد نظر ما رو دریافت کنه
- نوشتن برنامهای که کار دریافت اطلاعات رو انجام بده
تابع دریافت اطلاعات
public static void database_init(String db_address, String init_query, String query){ String conn = "jdbc:sqlite:/" + db_address; try { Connection connection = DriverManager.getConnection(conn); System.out.println("Connection established to the database."); Statement statement = connection.createStatement(); statement.execute(init_query); System.out.println("Successfully created the table."); statement.execute(query); System.out.println("Successfully ran the query"); } catch (SQLException throwables) { throwables.printStackTrace(); } }
همونطوری که میبینید، این تابع آدرس دیتابیس ما رو میگیره، اون رو به JDBC میده. پس از اون، یک اتصال با دیتابیس ایجاد میکنه و اگر اتصال موفقیتآمیز بود، یک پیام به شما میده. سپس، یک statement از دیتابیس ایجاد میکنه و پرس و جوی اولیه رو اجرا میکنه که در اینجا ساخت جدوله. پس از اون هم، کوئری نهایی یا اصل کاری اجرا میشه که در اینجا، میشه همون اضافه کردن تماس به جدول تماسها. همچنین تعریف شده که پس از اجرای هر پرسوجو، یک پیام مناسب چاپ بشه.
در مورد Connection, Statement و try catch ها نگران نباشید. اینها چیزایین که توسط IntelliJ IDEA هندل میشن. فقط موقع ساخت Connection حواستون باشه که بهتون خطا میده و ازتون میپرسه که «آیا در try catch قرارش بدم؟» و شما باید تاییدش کنید.
حالا که تابع ارتباط با دیتابیس رو داریم، وقتشه که اطلاعات رو از کاربر بگیریم. این کار رو من در تابع main میکنم.
تابع اصلی
در تابع اصلی، لازمه که نام، تلفن و ایمیل افراد رو با پیام مناسب، دریافت کنیم. این تابع اصلی برنامه من شد:
public static void main(String[] args) { // write your code here String query = "CREATE TABLE IF NOT EXISTS contacts(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, number TEXT NOT NULL, email TEXT NOT NULL);"; Scanner name = new Scanner(System.in); Scanner number = new Scanner(System.in); Scanner email = new Scanner(System.in); System.out.print("Enter a name: "); String input_name = name.nextLine(); System.out.print("Enter a phone number: "); String input_number = number.nextLine(); System.out.print("Enter an email address:"); String input_email = email.nextLine(); String insertion_query = "INSERT INTO contacts (name, number, email) VALUES (\"" + input_name + "\", \"" + input_number + "\"" + ", \"" + input_email +"\")"; database_init("/home/prp-e/playground/java.sqlite3", query, insertion_query); }
همونطور که میبینید ابتدا یک رشته به اسم query دارم که در اون توضیح دادم دقیقا میخوام چه جدولی با چه مشخصاتی برام ساخته شه. همچنین چک بشه که اگر جدول موجوده، ساخته نشه و روی همون جدول موجود دادههای جدید وارد بشن.
بعد از اون، سه تا شیء Scanner ایجاد کردم که ورودی رو از ترمینال کاربر بخونن. پس از اون، پیامهای مناسب رو چاپ کردم و مقداری که Scanner از شما دریافت کرده رو داخل رشتههای جدید ریختم.
پس از اون هم یه پرسوجوی بزرگ ساختم و در اون تعریف کردم که چیزایی که توسط Scanner ها خونده شدند، دقیقا کجا قرار بگیرند. در نهایت، هرچه بود و نبود رو دادم به تابع database_init .
برنامه کامل
این هم کد برنامه کامل که ببینید چی به چیه:
package com.haghiri75; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class Main { public static void database_init(String db_address, String init_query, String query){ String conn = "jdbc:sqlite:/" + db_address; try { Connection connection = DriverManager.getConnection(conn); System.out.println("Connection established to the database."); Statement statement = connection.createStatement(); statement.execute(init_query); System.out.println("Successfully created the table."); statement.execute(query); System.out.println("Successfully ran the query"); } catch (SQLException throwables) { throwables.printStackTrace(); } } public static void main(String[] args) { // write your code here String query = "CREATE TABLE IF NOT EXISTS contacts(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, number TEXT NOT NULL, email TEXT NOT NULL);"; Scanner name = new Scanner(System.in); Scanner number = new Scanner(System.in); Scanner email = new Scanner(System.in); System.out.print("Enter a name: "); String input_name = name.nextLine(); System.out.print("Enter a phone number: "); String input_number = number.nextLine(); System.out.print("Enter an email address:"); String input_email = email.nextLine(); String insertion_query = "INSERT INTO contacts (name, number, email) VALUES (\"" + input_name + "\", \"" + input_number + "\"" + ", \"" + input_email +"\")"; database_init("/home/prp-e/playground/java.sqlite3", query, insertion_query); } }
جمعبندی
گرچه این پروژه خیلی از مفاهیم شیگرایی رو در خود نداره، تا حد زیادی هم به نظر خودم کثیف نوشته شده و میشد از این بهتر باشه، اما پروژه خوبی برای سرگرم شدن به مدت ۲-۳ روز باشه. همچنین توضیح دوبارهش باعث شد که کمی کد رو تمیزتر کنم و سپس مطلب رو بنویسم.
این پروژه، برای به چالش کشیدن خیلی از تواناییهای شما، میتونه گزینه خوبی به حساب بیاد. فلذا اگر میخواید کمی توانایی برنامهنویسی خودتون رو محک بزنید، توصیه میکنم که شما هم این پروژه رو پیادهسازی کنید 🙂
موفق باشید!