Sử dụng Framework Hibernate trong Java Web Application
Hibernate Framework Framework trong phần mềm là một khái niệm dùng để chỉ những “cấu trúc dùng để hỗ trợ đã được định nghĩa sẵn” mà trong đó những dự án phần mềm khác có thể sử dung nó để phát triển. Một framework bao gồm những program hỗ trợ, core library và một ngôn ngữ lập ...
Hibernate Framework
Framework trong phần mềm là một khái niệm dùng để chỉ những “cấu trúc dùng để hỗ trợ đã được định nghĩa sẵn” mà trong đó những dự án phần mềm khác có thể sử dung nó để phát triển. Một framework bao gồm những program hỗ trợ, core library và một ngôn ngữ lập trình để giúp phát triển và gắn những thành phần khác nhau ứng dụng phần mềm lại với nhau. Hibernate là một trong những ORM Framework. Hibernate framework là một framework cho persistence layer. Như vậy sử dụng Hibernate framework giúp bạn phát triển ứng dụng nhanh và chỉ còn chú tâm vào những layer khác mà không cần chú tâm nhiều đến persistence layer nữa. Hibernate giúp lưu trữ và truy vấn dữ liệu quan hệ mạnh mẽ và nhanh. Hibernate cho phép bạn truy vẫn dữ liệu bằng ngôn ngữ SQL mở rộng của Hibernate (HQL) hoặc bằng SQL thuần.
Trong bài viết này tôi sẽ hướng dẫn các bạn làm quen với framework Hibernate qua những thao tác đơn giản. Hibernate cung cấp công cụ object relational mapping ORM như đã nói ở trên nên trong bài viết này tôi sẽ sử dụng luôn thế mạnh của framework này kết hợp cùng "JSF managed bean" và "JSF 2.x pages" để hiển lấy về dữ liệu và hiển thị ra giao diện web application.
Công cụ và môi trường phát triển
Trong bài viết này tôi sử dụng môi trường window 8.1 và cài đặt những IDE hỗ trợ sau:
- Java SE Development Kit 8u71
- Netbean IDE 8.1
- XamPP 5.6.15 - For Mysql Version 5.x
- GlassFish Server 4.1.1 - Nên chọn Netbean có sẵn server này (hoặc có thể dùng Jboss, Apache Tomcat...)
Các bạn có thể dùng các hệ quản trị cơ sử dữ liệu khác như Oracle DB, Sql Server ... IDE để soạn thảo code thì có thể dùng những lựa chọn khác như eclip, IntelliJ IDEA ... mỗi editor tool đều có sự khác biệt một chút nhưng đa phần đều support Hibernate.
Tạo mới một database
Trong bài viết này tối sẽ sử dụng luôn IDE netbean để tạo mới và thao tác với database. Để tạo một database các vào tab Services click chuột phải vào connection và chọn Create Datatbase...
ở đây tôi lấy tên database là liem_report_db các bạn có thể thay đổi tùy theo ý thích
Bây giờ chúng ta sẽ tạo ra một table có với tên là User ở đây là table demo nên tôi chỉ tạo ít field, các bạn có thể tùy biến để phù hợp với yêu cầu công việc
như vậy là chúng ta đã có table User nhưng chưa có dữ liệu nên chúng ta sẽ thêm môt ít dữ liệu demo. Để thực hiện câu lệnh query luôn trên IDE thì chúng ta click chuột phải vào connect và chọn Execute Command...
Test dữ liệu vừa thêm vào
Select * from User;
Và chúng ta có kết quả:
Lưu ý: những bước ở trên mục đích là để tạo một database và thiết lập dữ liệu trong đó để sử dụng sau này, nếu bạn đã có database rồi thì không cần phải thực hiện loại. Tên database, tables, fields có thể tùy biến theo ý thích.
Tạo mới một project Web Application
Để tạo mới một project trong Netbean khá dễ bạn chỉ cần thao tác theo những bước sau:
- Trên thanh Menu bạn chọn File > New Project (sử dung phím tắt Ctrl-Shift-N). Ở phần Category bạn chọn loại ứng dụng muốn tạo là Web Application sau đó click vào nút Next.
Ở bước này tôi sẽ yêu cầu chọn Server để Run project ở đây tôi chọn luôn server Glass Server 4.1.1 đi kèm sẵn trong bản Netbean. Các bạn có thể chọn server khác.
Đến bước này khá quan trọng, các bạn chọn JavaServer Faces và Hibernate 4.3.1 có thể version sẽ khác đi, tùy thuộc vào version của bản framework bạn bạn tích hợp vào Netbean
Sau đó click vào button Finish. Thế là chúng ta đã tạo ra một project được import các library của Hibernate và JSF (JavaServer Faces)
Hệ thống sẽ tự động sinh ra cho chúng ta một file có tên hibernate.cfg.xml nằm trong Source Packages > <default package> giờ chúng ta sẽ thêm một số config cho nó như sau:
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/liem_report_db</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"/> <property name="hibernate.show_sql">true</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
nếu các bạn để ý thì đây là những property cung cấp thông tin connection, việc này sẽ giúp cho Hibernate có thể thao tác với database của chúng ta. Thẻ cuối cùng hơi đặc biệt một chút
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
ở đây chúng ta khai báo class sẽ xử lý genarate ra câu lệnh sql. Trong bản Hibernate 4 tôi sử dụng đường dẫn package như vây, nếu bạn sử dụng bản khác (thấp hơn) thì thay đổi đường dẫn tương ứng
Tạo mới một class HibernateUtil.java
Để tạo mới một Hibernate Util class chúng ta thao tác như sau:
- Chuột phải vào Source Packages chọn New > Other để mở cửa sổ New File wizard.
- Chọn Hibernate từ list danh mục và ở khung đối diện File Types ta chọn HibernateUtil.java. Sau đó click vào button Next. Type HibernateUtil for the class name and dvdrental for the package. Click Finish.
Nhập vào tên cho class bạn muốn tạo. Ở đây tôi đặt tên là HibernateUtil cho dễ nhớ và chọn Package là app bạn có thể tùy biến tên class và package.
Tiếp theo chúng ta sẽ tạo một file Hibernate Reverse Engineering mục đích là để phục vụ cho việc mapping dữ liệu
Sau đó click vào button Next và chúng ta thấy hiện ra table có tên user như hình dưới:
Đây chính là tên table tôi tạo lúc đầu trong database, nếu các bạn tạo table khác thì tên nó sẽ hiện ra trong đó. Chúng ta chọn table và nhấn vào button Add move sang khung Selected Table sau đó chúng ta click button Finish
Hibernate Mapping Files and POJOs
Bây giờ chúng ta sẽ sử dụng Hibernate Mapping Files and POJOs để generate file từ table user đã chọn ở trước đó. Chúng ta thực hiện như sau:
- Chuột phải vào Source Packages chọn New > Other để mở New File wizard.
- Sau đó chúng ta chọn Hibernate ở khung bên cạnh chọn Hibernate Mapping Files and POJOs from Database sau đó click vào button Next.
- Trong dropdown list chọn file cấu hình hibernate.cfg.xml và hibernate.reveng.xml
- Check vào JDK 5 Language Features
- Check vào Domain Code và Hibernate XML Mappings để hệ thống nhận biết định dạng cần thiết để generate code.
- Đặt tên cho Package name tôi chọn là app. Sau đó click vào button Finish.
Ở công đoạn này nhiều người thường hay gặp phải message thông báo lỗi như hình dưới:
Nguyên nhân là do hệ thống không tìm được class ClassicQueryTranslatorFactory mà bạn đã cung cấp ở file cấu hình của Hibernate. Hãy kiểm tra lại version của hibernate và chỉnh sửa lại package cho đúng ở thuộc tính
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
Lưu ý: để nhanh chóng check xem đường dẫn đã đúng hay chưa bạn chỉ cần tạo mới một Class và import đường dẫn đó vào, nếu không tồn tại IDE sẽ báo đỏ, còn không thì đường dẫn là hợp lệ
Sau đó ta click vào Finish. Hệ thống sẽ tự động sinh ra 2 file mới trong app package đó là User.java và User.hbm.xml
Class User đã có sẵn các field và được mapping thành các property dễ dàng cho việc thao tác sau này. User.hbm.xml chứa thông tin mapping với user table: File: User.java
import java.util.Date; /** * User generated by hbm2java */ public class User implements java.io.Serializable { private int id; private String firstName; private String lastName; private String username; private String password; private Date created; public User() { } public User(int id, String username) { this.id = id; this.username = username; } public User(int id, String firstName, String lastName, String username, String password, Date created) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.username = username; this.password = password; this.created = created; } public int getId() { return this.id; } public void setId(int id) { this.id = id; } public String getFirstName() { return this.firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return this.lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public Date getCreated() { return this.created; } public void setCreated(Date created) { this.created = created; } }
File: User.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="app.User" table="user" catalog="liem_report_db" optimistic-lock="version"> <id name="id" type="int"> <column name="id" /> <generator class="assigned" /> </id> <property name="firstName" type="string"> <column name="first_name" length="50" /> </property> <property name="lastName" type="string"> <column name="last_name" length="50" /> </property> <property name="username" type="string"> <column name="username" length="20" not-null="true" unique="true" /> </property> <property name="password" type="string"> <column name="password" length="32" /> </property> <property name="created" type="time"> <column name="created" length="8" /> </property> </class> </hibernate-mapping>Test query với HQL Query
Hibernate hỗ trợ thực thi HQL query để phục vụ cho việc truy xuất dữ liệu trong quá trình phát triển, bước này để test xem việc config, dữ liệu để connect tới db, mapping data đã thành công hay chưa: Chuột phải vào file hibernate.cfg.xmlchọn Run HQL Query để mở cửa sổ HQL Query sau đó ta thực hiện câu lệnh truy vấn
from User
Và được kết quả như trong ảnh, nếu không hiện ra hoặc báo Generate erro thì bạn kiểm tra lại file cấu hình của hibernate
Tạo mới class UserHelper.java
Chúng ta tạo chuột phải vào app package để create một class tên có thể tùy biến, ở đây tôi đặt là UserHelper cho dễ nhớ:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package app; /** * * @author DUYLIEMPRO */ public class UserHelper { public UserHelper() { } }
Sau đó viết thêm các method để lấy dữ liệu ra:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package app; import java.util.ArrayList; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; /** * * @author DUYLIEMPRO */ public class UserHelper { Session session = null; List<User> userList; public UserHelper() { this.session = HibernateUtil.getSessionFactory().getCurrentSession(); } @SuppressWarnings("unchecked") public List<User> getUserList() { userList = new ArrayList<User>(); try { org.hibernate.Transaction tx = session.beginTransaction(); Query q = session.createQuery("from User as user"); userList = (List<User>) q.list(); } catch (Exception e) { userList = null; e.printStackTrace(); } return userList; } public User getUserByID(int userId) { User user = null; try { org.hibernate.Transaction tx = session.beginTransaction(); Query q = session.createQuery("from User as user where user.id=" + userId); user = (User) q.uniqueResult(); } catch (Exception e) { e.printStackTrace(); } return user; } }
Tạo mới JSF Managed Bean
Bước này mục đích là tạo ra bean class để lấy dữ liệu fill ra file view. Để tạo một bean class các bạn thực hiện như sau:
- Chuột phải vào source package chọn New > Other.
- Chọn JSF Managed Bean trong danh mục JavaServer Faces. Sau đó click Next.
- Nhập tên bean class UserController.
- Nhập tên package là app
- Nhập UserController cho ô name sau này sẽ được sử dụng gọi ở file view (managed bean) 6 Thiết lập Scope là Session. Sau đó click vào Finish.
File: UserController.java
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package app; import javax.inject.Named; import javax.enterprise.context.SessionScoped; import java.io.Serializable; /** * * @author DUYLIEMPRO */ @Named(value = "userController") @SessionScoped public class UserController implements Serializable { /** * Creates a new instance of UserController */ public UserController() { } }
Chúng ta sẽ viết các method xử lý lấy dữ liệu vào class này, ở đây tôi sẽ viết ví dụ 2 method, các bạn có thể thêm tùy ý:
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package app; import javax.inject.Named; import javax.enterprise.context.SessionScoped; import java.io.Serializable; import javax.faces.model.DataModel; import javax.faces.model.ListDataModel; /** * * @author DUYLIEMPRO */ @Named(value = "userController") @SessionScoped public class UserController implements Serializable { DataModel useList; UserHelper helper; private User current; /** * Creates a new instance of UserController */ public UserController() { helper = new UserHelper(); } public User getSelected() { if (current == null) { current = new User(); } return current; } public DataModel getUseList() { if (useList == null) { useList = new ListDataModel(helper.getUserList()); } return useList; } }
Lưu ý
Muốn sử dụng được những function này trong file view (.xhtml) thì bắt buộc chúng ta phải viết tên method theo quy ước "get" + tên method(Tên method phải viết hoa chữ cái đầu). Khi hiển thị trên file view thì tiền tố "get" tự động sẽ bị remove, chữ cái đầu trong tên method sẽ tự động chuyển sang thường.
Tạo mới file Web Pages
Ở đây tôi sẽ sử dụng template để dễ dàng hơn cho việc thiết lập layout chung cho nhiều page, để tạo một template các bạn làm như sau:
- Chuột phải vào source package chọn New > Other.
- Chọn Facelets Template trong danh mục JavaServer Faces. sau đó click Next.
- Tôi đặt tên là template và chọn layout style sử dụng CSS (Table đều được).
- Click vào button Finish. Kết quả là chúng ta được một file: template.xhtml trong thư mục web pages
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:h="http://xmlns.jcp.org/jsf/html"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <h:outputStylesheet name="./css/default.css"/> <h:outputStylesheet name="./css/cssLayout.css"/> <title>Facelets Template</title> </h:head> <h:body> <div id="top" class="top"> <ui:insert name="top">Top</ui:insert> </div> <div id="content" class="center_content"> <ui:insert name="content">Content</ui:insert> </div> </h:body> </html>
Tùy layout bạn chọn mà sẽ có nội dung khác nhau nhưng tất cả đều thẻ
<ui:insert name="content">Content</ui:insert>
Đây là nơi mà nội dung sẽ được chèn vào khi sử dụng template này.
Khi tạo mới ứng dụng hệ thống sẽ tự động tạo mới cho ta file index.xhtml trong thư mục Web Pages chúng ta sẽ sử dụng luôn file này để hiển thị dữ liệu. Tôi sẽ sử dụng JSF lib để sử dụng layout và hiển thị dữ liệu ra:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://xmlns.jcp.org/jsf/core"> <ui:composition template="./template.xhtml"> <ui:define name="content"> <h:form> <h:dataTable value="#{userController.useList}" var="item" border="0" cellpadding="2" cellspacing="0