วันอาทิตย์ที่ 2 พฤศจิกายน พ.ศ. 2557

Java Programming Bookstore Application (Series 2): Data Access Layer for the Bookstore Application

ก่อนเริ่มตอนนี้ควรไปติดตั้งและสร้าง database ก่อนนะครับ ตามลิงค์นี้ Series 1(Java Programming Bookstore Appication Series 1: Data Model for the Bookstore Application)  เมื่อพร้อมแล้วก็เริ่มกันเลย ใน series 2 เราจะสร้าง data access layer กัน ซึ่งใน layer นี้มีหน้าที่หลักในการรับหรือส่งค่าจาก database ผ่าน JDBC และนำข้อมูลที่ได้มา map เป็น Java objects  ซึ่งทำหน้าที่เป็น domain objects หน้าที่หลักของ data access layer คือคอยเป็นตัวกลางในการเก็บค่าหรือรับค่าจาก database จากตัวอย่างในรูปที่ 1 เป็นรูปแสดงการใช้ data access object (DAO) pattern สามารถช่วยให้เราเปลี่ยนรูปแบบของ data access layer ได้ง่ายขึ้น เช่น จาก JDBC ไปเป็น ORM (Hibernate, JPA หรืออื่น) โดยเราไม่ต้องแก้ไขฝั่ง client เลย

รูปที่ 1



อย่างแรกที่เราต้องทำคือสร้าง domain objects ขึ้นมาก่อนได้แก่ Book, Author, Category domain สามารถใช้ Eclipse IDE ในการสร้างได้ครับ (การพัฒนาโปรแกรม Java ด้วย Eclipse IDE)

ให้เราเปิด Eclipse IDE ขึ้นมาครับจากนั้นก็สร้าง Java project ใหม่ขึ้นมาโดยตั้งชื่อ project ว่า books

ให้สร้างไฟล์ class ขึ้นมาชื่อว่า Category ตามรูปที่ 2 

รูปที่ 2

และเขียน java code ตามตัวอย่างที่ 1

ตัวอย่างที่ 1 Model: Category (Category.java)
package com.apress.books.model;

package com.apress.books.model;

public class Category {
        private Long id ;
        private String categoryDescription ;

        public Long getId() {
               return id ;
       }

        public void setId(Long id) {
               this.id = id;
       }

        public String getCategoryDescription() {
               return categoryDescription ;
       }

        public void setCategoryDescription(String categoryDescription) {
               this.categoryDescription = categoryDescription;
       }

        public String toString() {
               return "Category - Id: " + id + ", Category Description: "
                           + categoryDescription;
       }
}

และทำเหมือนกันกับรูปที่ 2 โดยสร้าง class ชื่อว่า Author และ Book โดยเขียน java code ตามตัวอย่างที่ 2 และ 3

ตัวอย่างที่ 2 Model: Author (Author.java)
package com.apress.books.model;

public class Author {
        private Long id ;
        private Long bookId ;
        private String firstName ;
        private String lastName ;

        public Long getId() {
               return id ;
       }

        public void setId(Long id) {
               this.id = id;
       }

        public Long getBookId() {
               return bookId ;
       }

        public void setBookId(Long bookId) {
               this.bookId = bookId;
       }

        public String getFirstName() {
               return firstName ;
       }

        public void setFirstName(String firstName) {
               this.firstName = firstName;
       }

        public String getLastName() {
               return lastName ;
       }

        public void setLastName(String lastName) {
               this.lastName = lastName;
       }

        public String toString() {
               return "Author - Id: " + id + ", Book id: " + bookId + ", First Name: "
                           + firstName + ", Last Name: " + lastName ;
       }
}

ตัวอย่างที่ 3 Model: Book (Book.java)
package com.apress.books.model;

import java.util.List;

public class Book {
        private Long id ;
        private Long categoryId ;
        private String bookTitle ;

        private List<Author> authors ;
        private String publisherName ;

        public Long getId() {
               return id ;
       }

        public void setId(Long id) {
               this.id = id;
       }

        public Long getCategoryId() {
               return categoryId ;
       }

        public void setCategoryId(Long categoryId) {
               this.categoryId = categoryId;
       }

        public String getBookTitle() {
               return bookTitle ;
       }

        public void setBookTitle(String bookTitle) {
               this.bookTitle = bookTitle;
       }

        public List<Author> getAuthors() {
               return authors ;
       }

        public void setAuthors(List<Author> authors) {
               this.authors = authors;
       }

        public String getPublisherName() {
               return publisherName ;
       }

        public void setPublisherName(String publisherName) {
               this.publisherName = publisherName;
       }

        public String toString() {
               return "Book - Id: " + id + ", Book Title: " + bookTitle ;
       }
}

เมื่อเราได้ domain object แล้วจากนี้เราจะสร้าง interface ง่ายๆกันชื่อว่า BookDAO ซึ่งทำหน้าที่ในการ encapsulates การเข้าถึง database ของ web applicaltion หรือโปรแกรมทางฝั่ง client โดยเขียน java code ตามตัวอย่างที่ 4

ตัวอย่างที่ 4 BookDAO Interface (BookDAO.java)
package com.apress.books.dao;

import java.util.List;

import com.apress.books.model.Book;
import com.apress.books.model.Category;

public interface BookDAO {
        public List<Book> findAllBooks();

        public List<Book> searchBooksByKeyword(String keyWord);

        public List<Category> findAllCategories();

        public void insert(Book book);

        public void update(Book book);

        public void delete(Long bookId);
}

คำอธิบาย
  • findAllBooks() สำหรับดึงข้อมูลหนังสือทั้งหมดจาก database
  • SearchBooksByKeyword(String keyWord) ใช้สำหรับให้ user สามารถค้นหาหนังสือใน database โดยใช้ keyword ในการค้นหาซึ่งอาจจะเป็นชื่อหนังสือ หรือชื่อ หรือนามสกุลผู้เขียนก็ได้
  • findAllCategories() ใช้สำหรับดึงข้อมูลประเภทหนังสือทั้งหมดจาก database
และยังมี methods ที่เหลือที่ใช้สำหรับ CRUD (create, read, update, delete) เมื่อได้ interface จากนั้นเราจะสร้าง java code สำหรับการ implement BookDAO Interface กัน ตามตัวอย่างที่ 5

รูปที่ 3 ตัวอย่างการสร้างคลาสและ implement interface

ตัวอย่างที่ 5 BookDAOImpl
package com.apress.books.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.apress.books.model.Author;
import com.apress.books.model.Book;
import com.apress.books.model.Category;

public class BookDAOImpl implements BookDAO {

        // comment 1  
        static {
               try {
                     Class. forName("com.mysql.jdbc.Driver");
              } catch (ClassNotFoundException ex) {
              }
       }

        private Connection getConnection() throws SQLException {
               return DriverManager.getConnection("jdbc:mysql://localhost:3306/books",
                            "root", "password" );
       }

        private void closeConnection(Connection connection) {
               if (connection == null)
                      return;
               try {
                     connection.close();
              } catch (SQLException ex) {
              }
       }
       // comment 1

        public List<Book> findAllBooks() {
              List<Book> result = new ArrayList<>();
              List<Author> authorList = new ArrayList<>();

              String sql = "select * from book inner join author on book.id = author.book_id";

              Connection connection = null;

               try {
                     connection = getConnection();
                     PreparedStatement statement = connection.prepareStatement(sql);
                     ResultSet resultSet = statement.executeQuery();

                      while (resultSet.next()) {
                           Book book = new Book();
                           Author author = new Author();
                           book.setId(resultSet.getLong( "id"));
                           book.setBookTitle(resultSet.getString( "book_title"));
                           book.setCategoryId(resultSet.getLong( "category_id"));
                           author.setBookId(resultSet.getLong( "book_Id"));
                            author.setFirstName(resultSet.getString( "first_name"));
                           author.setLastName(resultSet.getString( "last_name"));
                           authorList.add(author);
                           book.setAuthors(authorList);
                            book.setPublisherName(resultSet.getString( "publisher"));
                           result.add(book);
                     }
              } catch (SQLException ex) {
                     ex.printStackTrace();
              } finally {
                     closeConnection(connection);
              }

               return result;
       }

        public List<Book> searchBooksByKeyword(String keyWord) {
              List<Book> result = new ArrayList<>();
              List<Author> authorList = new ArrayList<>();

              String sql = new StringBuilder()
                           .append( "select * from book inner join author on book.id = author.book_id")
                           .append( " where book_title like '%").append(keyWord.trim())
                           .append( "%'").append(" or first_name like '%" )
                           .append(keyWord.trim()).append( "%'")
                           .append( " or last_name like '%").append(keyWord.trim())
                           .append( "%'").toString();

              Connection connection = null;

               try {
                     connection = getConnection();
                     PreparedStatement statement = connection.prepareStatement(sql);
                     ResultSet resultSet = statement.executeQuery();

                      while (resultSet.next()) {
                           Book book = new Book();
                           Author author = new Author();
                           book.setId(resultSet.getLong( "id"));
                           book.setBookTitle(resultSet.getString( "book_title"));
                            book.setPublisherName(resultSet.getString( "publisher"));
                            author.setFirstName(resultSet.getString( "first_name"));
                           author.setLastName(resultSet.getString( "last_name"));
                           author.setBookId(resultSet.getLong( "book_id"));
                           authorList.add(author);
                           book.setAuthors(authorList);
                           result.add(book);
                     }
              } catch (SQLException ex) {
                     ex.printStackTrace();
              } finally {
                     closeConnection(connection);
              }

               return result;
       }

        public List<Category> findAllCategories() {
              List<Category> result = new ArrayList<>();
              String sql = "select * from category";

              Connection connection = null;

               try {
                     connection = getConnection();
                     PreparedStatement statement = connection.prepareStatement(sql);
                     ResultSet resultSet = statement.executeQuery();

                      while (resultSet.next()) {
                           Category category = new Category();
                           category.setId(resultSet.getLong( "id"));
                           category.setCategoryDescription(resultSet
                                         .getString( "category_description"));
                           result.add(category);
                     }
              } catch (SQLException ex) {
                     ex.printStackTrace();
              } finally {
                     closeConnection(connection);
              }

               return result;
       }

        public void insert(Book book) {
               // TODO Auto-generated method stub

       }

        public void update(Book book) {
               // TODO Auto-generated method stub

       }

        public void delete(Long bookId) {
               // TODO Auto-generated method stub

       }

}


จากตัวอย่างที่ 5 ในส่วนของ // comment 1 เป็น code สำหรับการใช้งาน JDBC 
  • getConnection() เราจะได้ driver implement ของ java.sql.Connection interface ซึ่งใช้ในการ run SQL Statement นั่นเอง เราจำเป็นต้องกำหนด MySQL Connector/J เราสามารถ downloadได้จาก http://dev.mysql.com/downloads/connector/j/ ตามรูปที่ 4
  • closeConnection(Connection connection) ทุกครั้งที่เรียกใช้งานเราต้องทำการเรียกเพื่อปิด connection เนื่องจาก connection แต่ละครั้งที่ทำการเปิดจะกินทรัพากรค่อนข้างสูง ถ้าไม่ปิดหรือลืมปิด connection เหล่านี้อาจจะเป็นเหตุให้ระบบมีปัญหาได้ในที่สุด 
  • ส่วน method อื่นๆ คือส่วนที่ได้ implement ตามที่ BookDAO ได้กำหนดไว้ (กลับไปดูคำอธิบายของ BookDAO)


รูปที่ 4




ตอนต่อไปติดตามได้ที่







อ้างอิง

ผู้เขียน: procodeblog

ไม่มีความคิดเห็น:

แสดงความคิดเห็น