بانک اطلاعاتی
Java SQL Server
ذخیره سازی اطلاعات در پایگاه داده, بسیار بهتر از ذخیره سازی در فایل ها و ارتباط مستقیم با فایل ها است. مزیت های آن نیز بر تمام برنامه نویسان آشکار است.
Structured Query Language و یا به اختصار SQL, یک زبان استاندارد است که برای انجام تراکنش با پایگاه داده مورد استفاده قرار میگیرد. این زبان در تمام پایگاه داده ها و تمام زبان های برنامه نویسی میتواند استفاده شود. به این ترتیب با استفاده از هر زبان برنامه نویسی, میتوان با هر پایگاه داده ای ارتباط برقرار کرد. در غیر این صورت نیاز بود تا برای هریک از زبان های برنامه نویسی, یکسری دستورات برای ارتباط با هر پایگاه داده در نظر گرفته شود. البته درجاوا, میتوان با استفاده از ساختار شی گرایی نیز با پایگاه داده ها ارتباط برقرار کرد. JOOQ نمونه ای از ارتباط با پایگاه داده به صورت شی گرایی است. اما استفاده مستقیم از SQL برای تراکنش با پایگاه داده, همچنان مورد استفاده قرار میگیرد.
اکنون در قالب مثال هایی ارتباط با پایگاه داده MySQL و همچنین تراکنش با آن را مورد بررسی قرار میدهیم. ابتدا باید یک Connector به برنامه اضافه کنیم.این connector در واقع برای برقراری ارتباط میان پایگاه داده و جاوا استفاده میشود. سپس Maven Dependency آن را به پروژه اضافه میکنیم:
1 2 3 4 5 6 7 8 9 10 11 | <groupId>zerotohero.vhdrjb</groupId> <artifactId>Java Mysql</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> </dependencies> |
ابتدا یک جدول در MySQL ایجاد میکنیم. این جدول مقادیر مربوط به اطلاعات کاربران را در خود نگهداری میکند.
Java SQL Server
1 2 3 4 5 6 | CREATE TABLE users ( code int not NULL , name VARCHAR(45) NULL , location VARCHAR(45) NULL , PRIMARY KEY (code) ) |
سپس یک کلاس متناظر با این جدول در جاوا ایجاد میکنیم
Java SQL Server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class User { private String name; private int code; private String location; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } } |
در ابتدا نیاز است تا ارتباط با پایگاه داده را برقرار کنیم. یک کلاس به نام JDBC Handler ایجاد میکنیم و در این کلاس تراکنش ها را مدیریت میکنیم. در Constructor این کلاس ارتباط با پایگاه داده را برقرار میکنیم.
Java SQL Server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class JDBCHandler { private Connection connection; final private static String dbName; final private static String username; final private static String password; final private static String server; static { dbName = "ZeroToHero"; username = ""; password = ""; server = ""; } public JDBCHandler() { try { Class.forName("com.mysql.cj.jdbc.Driver"); connection = DriverManager.getConnection("jdbc:mysql://"+server+"/"+dbName+"?&serverTimezone=UTC&useSSL=false&user="+username+"&password="+password); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } private void close() { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } |
ابتدا مقادیر حائز اهمیت برای ارتباط را در متغیر هایی قرار میدهیم. متد forName, یک MySQL Driver را برای برنامه نویس فراهم میآورد. سپس یک Connection برای تراکنش با پایگاه داده ایجاد میکنیم. متد close در کلاس, Connection ایجاد شده را از بین میبرد. توجه داشته باشید که بعد از هر تراکنش Connection ایجاد شده را ببنید و برای تراکنش جدید, یک Connection جدید ایجاد کنید.
اولین تراکنش افزودن اطلاعات یک شخص به پایگاه داده است. این دستور با استفاده از کلمه کلیدی Insert Into انجام میشود.
Java SQL Server
1 | insert into users (code, name, location) VALUES (value_code , value_name ,value_location ) |
users نام جدول است و بعد از آن ستون هایی که باید مقدار دهی شوند را مشخص میکنیم. ترتیب این ستون ها بسیار مهم است. در اینجا ابتدا ستون code و سپس ستون name مشخص شده است. در موقع وارد کردن اطلاعات و قرار دادن آن در دستور بالا نیز باید این ترتیب رعایت شود. در غیر این صورت اطلاعات نادرستی به جدول وارد میشود.
Java SQL Server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public boolean insert(User user) { try { PreparedStatement statement = connection.prepareStatement("INSERT INTO users (code,name,location) values (?,?,?)"); statement.setInt(1, user.getCode()); statement.setString(2, user.getName()); statement.setString(3, user.getLocation()); statement.executeUpdate(); close(); return true; } catch (SQLException e) { e.printStackTrace(); } return false; } |
در کد بالا, دستور SQL در یک Prepared Statement قرار داده شده است. علت استفاده از Prepared Statement, تامین امنیت است. اگر با دستورات SQL Injection, که یکی از روش های حمله به پایگاه داده است, آشنا باشید علت استفاده از این کلاس برای شما واضح است. با استفاده از این کلاس, مقادیری که قرار است به پایگاه داده افزوده شوند را با علامت سوال (?) مشخص میکنیم و با استفاده از متد های کلاس Prepared Statement مقادیر را به آن اضافه میکنیم.این روش ارتباط را نسبت به آسیب پذیری SQL Injection امن میکند. در نهایت با استفاده از متد execute Update دستور را اجرا میکنیم و connection را میبندیم.
1 2 3 4 5 6 | JDBCHandler jdbcHandler=new JDBCHandler(); User user = new User(); user.setCode(10); user.setName("Vahid Rajabi"); user.setLocation("Iran"); jdbcHandler.insert(user); |
دستور بعدی, دستور واکشی اطلاعات است. اطلاعاتی که به پایگاه داده وارد شده اند, باید واکشی و خوانده شوند تا مورد پردازش قرار گیرند. دستور select برای واکشی اطلاعات استفاده می شود.
1 | SELECT (column1,column2,...) FROM tabel where column1=condition |
بعد از کلمه کلیدی Select, ستون هایی که میخواهیم مقادیر آن ها را دریافت کنیم را مشخص میکنیم. اگر تمام ستون ها را بخواهیم دریافت کنیم, از “*” استفاده میشود. سپس نام جدول را مشخص میکنیم و با استفاده از کلمه کلیدی Where میتوان اطلاعاتی که با شرط خاصی همخوانی دارند را دریافت کنیم. تمام قوانین قابل استفاده در دستورات شرطی, در SQL نیز قابل استفاده است.
1 | select * from users WHERE location = "Iran" |
اکنون میخواهیم این واکشی را با استفاده از کد جاوا انجام دهیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public ArrayList<User> select() { ArrayList<User> users = new ArrayList<User>(); try{ PreparedStatement statement = connection.prepareStatement("select * from users where location='Iran'"); ResultSet resultSet = statement.executeQuery(); while (resultSet.next()) { User user=new User(); user.setCode(resultSet.getInt(resultSet.findColumn("code"))); user.setLocation(resultSet.getString(resultSet.findColumn("location"))); user.setName(resultSet.getString(resultSet.findColumn("name"))); users.add(user); } close(); }catch (SQLException e) { e.printStackTrace(); } return users; } |
ابتدا یک لیست از کلاس User ایجاد میکنیم که نتیجه جستجو ما را مشخص میکند. کد را در کلاس Prepared Statement قرار میدهیم و با استفاده از متد execute query دستور را اجرا میکنیم. برای دریافت مقدار هر ستون نیاز است تا شماره آن ستون را در متد های get قرار دهید. اما معمولا برای جلوگیری از اشتباه, شماره ستون را نیز با استفاده از متد find column دریافت میکنیم. به این ترتیب نام ستون را در متد find column قرار میدهیم و نتیجه را در متد های get استفاده میکنیم.
برای بروزرسانی مقادیر در جدول از کلمه کلیدی update استفاده میکنیم.
1 | UPDATE table SET column1 = new_value where column2 = condition |
اکنون برای انجام تراکنش بروزرسانی, به این صورت عمل میکنیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public boolean update() { try { PreparedStatement statement = connection.prepareStatement("update users set name = ? where code=? "); statement.setString(1, "vhdrjb"); statement.setInt(2, 10); statement.executeUpdate(); close(); return true; } catch (SQLException e) { System.out.println(e.getMessage()); } return false; } |
و شیوه استفاده از آن نیز مانند متد های قبل است.
برای حذف یک مقدار از پایگاه داده نیز به این صورت عمل میکنیم:
1 | delete from table where column = condition |
و کد جاوا آن به این صورت است:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public boolean delete() { try { PreparedStatement statement = connection.prepareStatement("DELETE FROM users where code = ?"); statement.setInt(1, 10); statement.executeUpdate(); close(); return true; } catch (SQLException e) { System.out.println(e.getMessage()); } return false; } |