EJB viết tắt của Enterprise JavaBeans ( tui không dịch ) Nó có đặc điểm cơ bản sau + nằm trong lòng các container chính là các application server phía server side ( điển hình là JBOSS và GlassFish ) + chỉ giao tiếp với các chương trình viết bằng java ( có giao tiếp với webservice viết bằng Java ) miễn là thông qua JNDI các chương trình đó tìm được đúng Bean cần dùng
Về các loại Bean trong EJB Bean thực ra tương đương với remote component trong .NET nó có 3 loại chính ( có thể chia ra làm 5 loại )
+ Stateless Session Beans : ( loại thứ nhất của Session Bean )nôm na là nó chứa các nghiệp vụ logic mà public ra bên ngoài cho phép các hệ thống khác có thể truy nhập. + Stateful Session Beans : ( loại thứ haicủa Session Bean ) giống với loại trên nhưng 2 loại bean này khác nhau đúng 1 điểm : nếu giữa các người dùng sử dụng đến thuộc tính của Session Beans thì với Stateful Session Beans, lần sử dụng sau vẫn lưu giá trị của lần trước đối với người dùng đó còn Stateless Session Bean thì không phân biệt
Nôm na là : nều bạn muốn xài biến Session như viết web asp thì nó chính là Stateful Session Beans, còn nếu bạn muốn biến global thì nó sẽ là Session Beans.
Hai loại trên dùng để ánh xạ 1 bản ghi trong csdl ở đâu đó mà Application có thể giao tiếp, hoặc đơn giản chỉ là 1 csdl bằng text do bạn tự quy định. CSDL ở đây có thể là tất cả những ghi có thể lưu trữ thông tin Hai loại này khác nhau đúng chữ "Bean" và "Container". Nó cũng nói lên đặc điểm khác nhau điển hình của chúng. đó là : BMP việc giao tiếp csdl bạn phải tự quan lý ( tự code ), CMP việc giao tiếp csdl là tự động bạn chỉ cần khai báo cấu hình cho bean này ánh xạ đến csdl Vì vậy CMP giới hạn hơn BMP vì nó chỉ có thể giao tiếp với các hệ quản trị csdl, còn BMP do các bạn viết code nên nó có thể lưu cả trên file txt, xml, excel ... miễn lưu được dữ liệu. Và SUN cũng khuyên chúng ta cho các client sử dụng BMP và CMP thông qua các loại Session Bean + Message driven Bean : loại Bean này Sun đưa vào trong hệ thống EJB theo tôi thì nó là con nuôi của Beans . Vì khi triển khai code Bean thì loại này chẳng giống gì 4 loại Bean trên. Tuy nhiên nó rất quan trọng. Các hệ thống ngân hàng giao tiếp thanh toàn tài khoản với nhau chỉ dùng message cho nên đây là đất võ của Message driven Bean. Có 2 loại Bean trong Message driven Bean và các loại Bean này năm trong MOM (Message Oriented Middleware) Hai loại đó là Queue và Topic. Ứng với mỗi loại Bean này MOM có 2 loại hàng đợi phù hợp cho nó. Quese thì chỉ cho 1 client gửi 1 message tới 1 người ( ví dụ chat yahoo ) Topic thì chỉ cho 1 client gửi 1 message tới nhiều người ( ví dụ chat room trong yahoo ) miễn là người nhận có đăng ký với hàng đợi message. ---------------------------------------------------- cụ thể hoạt động của mỗi loại Bean thì rắc rối nhưng 4 loại trên thì cùng nguyên tắc, JMS có nguyên tắc khác.
"Model-View-Controller" is a way to build applications that promotes complete separation between business logic and presentation. It is not specific to web applications, or Java, or J2EE (it predates all of these by many years), but it can be applied to building J2EE web applications.
The "view" is the user interface, the screens that the end user of the application actually sees and interacts with. In a J2EE web application, views are JSP files. For collecting user input, you will have a JSP that generates an HTML page that contains one or more HTML forms. For displaying output (like a report), you will have a JSP generates an HTML page that probably contains one or more HTML tables. Each of these is a view: a way for the end user to interact with the system, putting data in, and getting data out.
When the user clicks 'Submit' in an HTML form, the request (complete with all the form information) is sent to a "controller". In a J2EE web application, controllers are JavaBeans. The controller's job is to take the data entered by the user (in the HTML form that the JSP generated) and pass it to the "model", which is a separate Java class that contains actual business logic. The model does whatever it does (for instance, store the user's data in a database), then returns some result back to the controller (perhaps a new ID value from the database, or perhaps just a result code saying "OK, I'm done"). The controller takes this value and figures out what the user needs to see next, and presents the user with a new view (for instance, a new JSP file that displays a confirmation that the data they entered was successfully saved).
This all sounds like a lot of work, and it is. But there is a point to architecting applications this way: flexibility. The beauty of model-view-controller separation is that new views and controllers can be created independently of the model. The model -- again, this is pure business logic -- knows nothing of HTML forms or JSP pages. The model defines a set of business functions that only ever get called by controllers, and the controllers act as proxies between the end user (interacting with the view) and the business logic (encapsulated in the model). This means that you can add a new view and its associated controller, and your model doesn't know or care that there are now two different ways for human beings to interact with the application.
For instance, in an application with complicated data entry screens, you could add a JSP that generated a quick-edit form with default values instead of a longer, standard form. Both JSPs (the short form and the long form) could use the same controller; default values could simply be stored in the HTML
Generates html to display any errors that may have occurred during invocation of the validate() method. Generates There is a hidden element here which is invisible. :-)
Generates . Generates . A link to an external site Generates an html link. Generates for use in collecting information that should not be shown on-screen. Generates a radio button (). Generates .
Generates
Generates to submit form data entered by the user.
The purpose of the ActionForm class is to contain and provide validation of the user-input data. This class is subclassed for application specific customization.
Here is a template for a customized ActionForm class with markers denoting where special items should be located in the class with $ symbols.
public class $THE_NAME_OF_THIS_FORM_CLASS$ extends ActionForm {
// The attributes of the class should go here // For example, private int age; $PRIVATE_ATTRIBUTES_FOR_THIS_CLASS$
// The constructor method for this class public $THE_NAME_OF_THIS_FORM_CLASS$() { }
// The method to invoke when a reset occurs public void reset(ActionMapping mapping, HttpServletRequest request) { }
// The method providing validation of this classes attributes public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors();
if ($SOME_CODE_TO_VALIDATE_AN_ATTRIBUTE_OF_THIS_CLASS_RETURNING_true_ON_SUCCESS$) { // } else { // Add an error to the errors to be returned that designates the validation of the // current attribute failed. The information will come from the Application Resources. errors.add("$THE_ATTRIBUTES_NAME$", new ActionError("$SOME_KEY_FROM_THE_ApplicationResources.properties_FILE$")); }
// Return the errors return errors; }
$ACCESSOR_AND_MUTATOR_METHODS_FOR_THE_ATTRIBUTES_OF_THIS_CLASS$ // For example, // public int getAge() { return age; } // public void setAge(int newAge) { age = newAge; }
public final class $THE_NAME_OF_THIS_ACTION_CLASS$ extends Action {
// The constructor method for this class public $THE_NAME_OF_THIS_ACTION_CLASS$() { }
// The method used for processing the user-input public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
This example demonstrates the use of Struts for a simple web application using HTML forms. The application will request a name from the user and will display that name on the page containing the form.
The NameForm class will be used for storing the user input. The SetNameAction class will receive an instance of the NameForm class containing the user input on which to perform its action. An instance of the Name class will be stored in the user's session to represent the name that was last entered.
Do this:
Create the directory structure. The root directory is SimpleStruts, and it has the standard WEB-INF directory with classes inside, and com/masslight/strutsExampleClasses inside that. It also has a lib directory within WEB-INF, which is something we haven't seen before; we'll see in a minute what goes there.
Copy the Struts tag library descriptor files into WEB-INF. The files struts.tld, struts-bean.tld, struts-form.tld, struts-html.tld, struts-logic.tld, and struts-template.tld are available in the lib directory of your Struts installation.
Copy the Struts parser, struts.jar, into WEB-INF/lib/. This file is available in the lib directory of your Struts installation
Create the tag descriptor library file for any custom tags you may use beyond the Struts tags. In this case, the file defines no custom tags, but it's good practice to have it in place, in case you need to add your own tags later.
code/Chapter4/SimpleStruts/WEB-INF/app.tld
1.0 1.1 utility Empty tag library template
Create the struts-config.xml file.
There are three main sections to a struts-config.xml configuration file. They are the "Form Bean Definitions" section, the "Global Forward Definitions" section, and the "Action Mapping Definitions" section.
The NameForm class will be defined in the form bean definition section, where it will receive a name for use in the "Action Mapping Definitions" section. The global forward definition section defines a forward called "success".
A global forward is defined in the "Global Forward Definitions" section. Whenever this forward is referenced, index.jsp will be displayed.
The "Action Mapping Definitions" is the most important section within the configuration file. This section takes a form defined in the "Form Bean Definitions" section and maps it to an action class.
Here is what the struts-config.xml configuration file will look like for this application:
The web.xml web application configuration file will need to define the servlet ActionServlet, to which control will be transferred whenever an appropriate URL pattern is accessed. The servlet is defined just as any other servlet will be defined. The URL pattern is specified by a servlet mapping. For this application, the URL pattern is any requested resource that ends with a .do extension.
In order to use the Struts tags, the .tld files describing the tags will need to be included in the configuration file. The references to these tags are made just as they were for our own custom tags in the previous chapter. The Struts framework is simply a complex set of tag libraries (struts*.tld), with associated code (struts.jar).
The web.xml configuration file should look like this:
The ApplicationResources.properties file provides resources that will be used by any subclassed Struts classes (for example, SetNameAction). This resources file provides a place to define prompts, labels that will display on buttons, and other information that may change. By placing this information in the ApplicationResources.properties file, recompiling any servlets used in the application can be avoided, as well as encouraging separation of logic and presentation.
The ApplicationResources.properties file looks like this:
button.save=Change name button.reset=Reset error.name.required=To change the name, a name must be entered prompt.name=Enter name: welcome.title=A Simple Application
Instances of the Name class are placed in the user sessions. Only one will exist in any particular user session. It provides methods for accessing and mutating a name.
public void setName(String name) { this.name = name; }
public String toString() { StringBuffer sb = new StringBuffer("Name[name="); sb.append(name); sb.append("]"); return (sb.toString()); }
}
The NameForm class stores and validates the user input. It provides methods for accessing and mutating the data in the form. Notice how the validate method uses information from the ApplicationResources.properties file.
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if ((name == null) || (name.length() <>
The SetNameAction class has a perform method, which receives an instance of the NameForm class containing the user input.
Although the perform method here operates directly on the form data, in a real-world application it should instead delegate this duty to a business logic object. (We will see how this works in chapter 7, once we learn about EJBs.) The perform method takes the name from the form and creates a new instance of the Name class, which is placed inside the session. If a bean by that name is already present in the session, it is replaced by the new instance.
Notice how the class uses this code:
return (mapping.findForward("success"));
to display the next JSP. A new forward could have been defined in the struts-config.xml called "failed" or "DEFCON1". If any of the code in the perform method had failed, the user could be forwarded to the JSP page defined in the forward definition.
Place the following code in the SetNameAction.java file:
if ("Set".equals(action)) { name = null; name = new Name(); name.setName(nameform.getName()); }
session.setAttribute("name", name);
if (mapping.getAttribute() != null) {
if ("request".equals(mapping.getScope())) request.removeAttribute(mapping.getAttribute()); else session.removeAttribute(mapping.getAttribute());
}
return (mapping.findForward("success"));
}
}
The view of the application is done with the JSP index.jsp. It represents the user interface and allows the user to interact with the application.
Information from the ApplicationResources.properties file is used for the page title, prompts, and the Submit button label. This is done with the tag. The attribute "key" is used to specify the application resource to lookup in the ApplicationResources.properties file.
Any errors that were found by the validate method of the NameForm class are displayed by using the tag.
The action attribute of the tag is "setName". When the user clicks the Submit button, the action defined for setName in struts-config.xml is invoked.
A text field is created and associated with the property "name" in an instance of the NameForm class by using the attribute property in the tag. Two optional attributes are used to define the length and the maximum characters to accept.
A new tag is introduced from the Struts logic tag library. checks to see if a bean whose name is specified with the name attribute exists. If a user has previously entered a name and submitted it without any errors, then a bean by that name will exist. Whenever the bean is found, the information in the enclosed by the tags are included in the html that is generated. Don't worry about this for now; the next chapter will discuss handling conditional logic in Struts.
The tag is used to display the value of the property in the bean specified by the "property" and "name" attributes.
Add the following to the form and appropriate methods and variables to the Name, SetNameAction, and NameForm classes to process the information correctly:
a set of radio buttons for selection of contentness (happy or sad)
a set of checkboxes to allow the user to select favorite types of music (rock, gospel, folk, country, and classical)
a selection to choose an age range (18-24, 25-40, 41-67, 67-300)
a text-area for entering side notes about the person (5 rows and 40 columns)
Exercise 2. Think
What happens when the browser is closed and the site is visited once again? How can this be avoided?
• Framework là một khái niệm trong phát triển phần mềm dùng để chỉ những “cấu trúc hỗ trợ được định nghĩa” mà trong đó những dự án phần mềm khác có thể được sắp xếp vào đó và phát triển.
• ORM (Object Relational Mapping) framework là một cơ chế cho phép người lập trình thao tác với database một cách hoàn toàn tự nhiên thông qua các đối tượng. Lập trình viên hoàn toàn không quan tâm đến loại database sử dụng, SQL, … 1.1.2. Persistence Layer
• “Tier” và “Layer”: tier thường được gắn với phần cứng về mặt vật lý (physical) còn layer thì dính đến vấn đề cách thức tổ chức bên trong của ứng dụng. Việc phân chia tier là “trong suốt” (transparent) đối với ứng dụng về mặt luận lý (logical). Điều này có nghĩa là khi ta phát triển một ứng dụng, chúng ta không bận tâm đến các thành phần (component) sẽ triển khai (deploy) ra sao mà chỉ chú ý là chúng ta sẽ tổ chức ứng dụng thành những layer như thế nào.
• Peristence layer: một ứng dụng có thể được chia làm 3 phần như sau: giao diện người dùng (presentation layer), phần xử lý nghiệp vụ (business layer) và phần chứa dữ liệu (data layer). Cụ thể ra, business layer có thể được chia nhỏ thành 2 layer con là business logic layer (các tính toán nhằm thỏa mãn yêu cầu người dùng) và persistence layer. Persistence layer chịu trách nhiệm giao tiếp với data layer (thường là một hệ quản trị cơ sở dữ liệu quan hệ - Relational DBMS). Persistence sẽ đảm nhiệm các nhiệm vụ mở kết nối, truy xuất và lưu trữ dữ liệu vào các Relational DBMS. 1.1.3. Hibernate Framework
• Hibernate là một trong những ORM Framework
• Hibernate framework là một framework cho persistence layer. Như vậy, nhờ có Hibernate framework mà giờ đây khi bạn phát triển ứng dụng bạn chỉ còn chú tâm vào những layer khác mà không phải bận tâm nhiều về persistence layer nữa.
• Hibernate: là một dịch vụ lưu trữ và truy vấn dữ liệu quan hệ mạnh mẽ và nhanh.
Hibernate giúp bạn phát triển các class dùng để lưu trữ dữ liệu theo cách thức hướng đối tượng: association, inheritance, polymorphism, composition và collections Hibernate cho phép bạn thực hiện các câu truy vấn dữ liệu bằng cách sử dụng ngôn ngữ SQL mở rộng của Hibernate (HQL) hoặc là ngôn ngữ SQL nguyên thủy cũng như là sử dụng các API. Hibernate được license theo LGPL (Lesser GNU Public License). Theo đó, bạn có thể thoải mái sử dụng Hibernate trong các dự án open source hoặc các dự án thương mại (commercial). 1.2. Cài đặt và sử dụng
1.2.1. Cài đặt
• Việc cài đặt Hibernate rất đơn giản. Hibernate được build thành 1 tập tin JAR. Bạn chỉ cần download tập tin này và lưu nó vào thư mục LIB của project mà bạn đang phát triển.
• Download JDBC Driver cho database (cũng được build thành 1 tập tin JAR).
• Thêm các thành phần liên quan của Hibernate vào classpath.
1.2.2. Sử dụng
• Việc sử dụng Hibernate cũng rất đơn giản. Bạn cần gì ở một persistence layer? Đó là chúng sẽ truy xuất cũng như lưu trữ dữ liệu của bạn xuống database. Về mặt vật lý, theo mô hình dữ liệu quan hệ, dữ liệu của bạn sẽ bao gồm các thực thể (entity) có quan hệ với nhau. Và khi hiện thực cụ thể hơn mức database, chúng sẽ được đại diện bởi các table, bởi các ràng buộc khóa ngoại, khóa chính, … Hibernate cũng như vậy.
• Mỗi table trong database là một object trong Hibernate. Do đó, bạn cần có một java bean cho mỗi table trong database. Các java bean này sẽ có các getters / setters và một số ngoại lệ theo quy ước của Hibernate.
• Tiếp theo để Hibernate biết một object được “ánh xạ” (mapping) như thế nào với table trong database, Hibernate yêu cầu bạn cung cấp tập tin đặc tả gọi là mapping file. Theo quy ước của Hibernate, các mapping file này có đuôi là .hbm.xml và phải hợp lệ với DTD (Document Type Definition) mà Hibernate đã đưa ra. Trong các mapping file này, bạn sẽ đặc tả các mối quan hệ giữa property của object với field của table. Tức là bạn giúp cho Hibernate hiểu “mối quan hệ giữa các object” tương ứng như thế nào với “mối quan hệ giữa các field”.
• Tiếp theo nữa, bạn cần có 1 tập tin để Hibernate bắt đầu: hibernate.cfg.xml. Có thể nói tập tin này được load lên đầu tiên khi bạn “khởi động” Hibernate. Trong tập tin này, bạn đặc tả các thông tin sau:
SQL Dialects. JDBC connection property: connection (url, driver class name, user name, password, pool size). Hoặc là datasource property: datasource JNDI name, user name, password. Hibernate configuration: show sql, … Hibernate cache configuration. Hibernate transaction configuration. Miscellaneous configuration. 1.3. Các tập tin config
1.3.1. hibernate.cfg.xml
• Tập tin này bắt đầu bằng thẻ và kết thúc với thẻ .
• Thẻ là thẻ con của thẻ . Những thể con của thẻ được sử dụng để định nghĩa properties và resources của session-factory.
• Để định nghĩa các properties của session-factory, ta sử dụng thẻ class.
name của thẻ property là property của session-factory. Những properties của session-factory có thể là: o hibernate.connection.driver_class o hibernate.connection.url o hibernate.connection.username o hibernate.connection.password o hibernate.connection.pool_size o show_sql o dialect o hibernate.hbm2ddl.auto o …
class là các giá trị của các properties của session-factory.
Ví dụ: com.mysql.jdbc.Driver
• Để định nghĩa resouces của session-factory, ta sử dụng
resource là đường dẫn url của hbm.xml file.
1.3.2. hibernate.properties
Khai báo các properties trong 1 file tên là: hibernate.properties, chỉ cần đặt file này trong classpath của ứng dụng. Nó sẽ tự kiểm tra và đọc khi Hibernate khởi chạy lần đầu tiên, là khi tao 1 Configuaration object. Tương tự như hibernate.cfg.xml, hibernate.properties cũng để khai báo các thông số, nhưng hibernate.properties thường được kết hợp với spring config. 1.4. Tập tin hbm.xml – tập tin ánh xạ:
1.4.1. Cấu trúc cơ bản • Bắt đầu bằng và kết thúc với .
• Từng bảng trong CSDL được đinh nghĩa bằng thẻ và chứa những thuộc tính (attributes):
name: là tên của lớp đối tượng dữ liệu (data object class) (của bảng tương ứng trong CSDL). table: là tên của bảng trong CSDL.
• Thẻ có các thẻ con sau:
Thẻ : để định nghĩa id của bảng. Nó có những thuộc tính sau: o name: là tên property của đối tượng dữ liệu (data object). o column: là tên của cột trong CSDL. o type: là kiểu dữ liệu của cột. Chú ý: đây là một kiểu của Hibernate chứ không phải của kiểu dữ liệu của Java hay của CSDL.
Thẻ cũng có thẻ con sau: o Thẻ để cho biết loại id trong table của CSDL (được gàn là: no-generate, increment: được tạo ra bởi hibernate (không nên sử dụng), identity: tự động tạo ra bởi CSDL, native: chọn các kiểu tạo khác như sequence của Oracle.
Thẻ để chỉ ra một cột bình thường, có cùng thuộc tính như thẻ ngoại trừ việc thẻ này không có thẻ con .
1.4.2. Mapping types
Mapping types là những kiểu dữ liệu mà khi khai báo ở tập tin hbm.xml sẽ dược ánh xạ tương ứng. Hibernate có một số kiểu dữ liệu sẵn có mà Hibernate đã định nghĩa, goi là Built-in mapping types. Ngoài ra, bạn cụng có thể tự định nghĩa một kiểu riêng của bạn. 1.5. org.hibernate.cfg.Configuration
1.5.1. Configure()
Sử dụng các phép ánh xạ (mappings) và các đặc tính được xác định (properties specified) trong một tài nguyên ứng dụng (application resource) được đặt tên là hibernate.cfg.xml. Nhiều người thích tập trung cấu hình Hibernate bằng cách này thay vì thêm tham số vào Configuration trong code của ứng dụng.
1.5.2. addResource(String path)
Đọc các mappings trong một application resource (sử dụng cái này khi không muốn sử dụng file .cfg.xml để config).
1.5.3. addClass(java.lang.Class class)
Đọc mapping files của class đầu vào (ví dụ, có lớp User and và có User.hbm.xml, khi sử dụng addClass(User.class) nghĩa là thêm User.hbm.xml resource file vào Configuration).
1.5.4. setProperties(java.util.Properties)
Ta có thể class, driver, user, password (,…) để truy cập vào database bằng cách sử dụng .cfg.xml file hoặc .properties file. Khi sử dụng .properties file, phải sử dụng phương thức này để config. 1.6. org.hibernate.Session
1.6.1. Cách sử dụng
//open a session Session session = sessionFactory.openSession(); //begin a transaction Transaction tx = session.beginTransaction();
User user = session.get(User.class, new Long(100));
Nếu chúng ta sử dung phương thức này để lấy User với cùng id trong cùng session, phương thức này sẽ trả về một instance của User (không phải 2 instance).
Ví dụ:
User user1 = session.get(User.class, new Long(100)); User user2 = sessoon.get(User.class, new Long(100));
=> user1= user2
Ta có thể rút trích bằng phương thức load(). Sự khác biệt giữa phương thức load() và get() là ta có thể không rút trinh một đối tượng được trả về bởi phương thức load() khi session đã bị đóng (close).
1.6.3. lock()
Sau khi lấy một đối tượng từ CSDL, ta đóng session lại. Cái việc này sẽ làm cho đối tượng trở thành intacnce bị tách biệt (detached instance). Nó có thể được kết hợp lại (reassociated) với Session mới bằng cách gọi lock(). Phương thhức này sẽ ném ra một ngoại lệ là HibernateException khi nó không thể tìm thấy id trong CSDL bằng với id của đối tượng. HibernateException cũng sẽ bị ném khi bạn thay đổi id của đối tượng sau khi kết hợp lại.
Ví dụ:
Session session = sessionFactory.openSession(); User user = (User) session.get(User.class, new Long(100)); Session.close(); //user becomes detached
Các đối tượng được rút trích bởi phương thức session.load() hay session.get() đã được kết hợp với CSDL. Chúng ta chỉ cần set những giá trị mới và commit cái transaction để update. Objects that are reassociated are also the same.
Ví dụ:
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); User user = (User) session.get(User.class, new Long(100)); user.setName(“ABC”); tx.commit(); session.close();
Detached objects có thể thường được cập nhật bởi phương thức update(). Các đối tượng được cập nhật cũng được kết hợp lại với session mới.
Ví dụ:
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); User user = (User) session.get(User.class, new Long(100)); user.setName(“ABC”); tx.commit(); session.close();
// pretend that user has 2 properties, first is // name, second is password; and the values by // roster are “AAA” and “BBB”. user.setName(“ABC”);//new name value Session session2 = sessionFactory.openSession(); tx = session2.beginTransaction(); session2.update(user); //update and reassociated user.setPassword(“EFG”); tx.commit(); session2.close();
//the new values of user in turn of name and password are “ABC” and “EFG”
Một StaleStateException sẽ được ném khi ta cập nhật một đối tượng không tồn tại.
1.6.5. Insert
Để insert một đối tượng vào CSDL, ta sử dụng phương thức save(). Sau khi gọi phương thức này, đối tượng sẽ được kết hợp lại với session.
Ví dụ:
User user = new User(); user.setId(120); user.setName(“Name”); user.setPassword(“Password”); Session session = sessionFactory.openSession(); Transaction tx = Session.beginTransaction(); session.save(user); user.setName(“NewName”); tx.commit(); session.close(); /* after executing the code above, in database, there is a row containing values as follow: id = 120, name = “NewName”, password = “Password” */
1.6.6. Delete
Để delete một dòng trong CSDL, ta phải đưa ra một đối tượng tương ứng với bảng trong CSDL. Nhưng ta không cần phải đưa hết giá trị vào các thuộc tính của đối tượng, ta chỉ cần set cái id của đối tượng. Phương thức này sẽ ném ra một ngoại lệ (StaleStateException) khi ta muốn xóa một đối tượng có id mà id này ko tồn tại trong CSDL.
Ví dụ:
User user = new User(); User.setId(100); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); session.delete(user); tx.commit(); session.close(); 1.6.7. Ngoại lệ ConstraintViolationException Khi bạn có gắng để save, update, delete những đối tượng mà sẽ xâm phạm các ràng buộc CSDL (như duplicate identifier, not-null constraint, unique constraint), ngoại lệ ConstraintViolationException sẽ được ném ra.
1.7. org.hibernate.Transaction
1.7.1. Understanding database transactions
• Một database transaction nhóm các thao tác truy cập dữ liệu. Một transaction sẽ kết thúc bằng một trong 2 cách sau đây: committed hoặc rolled back.
• Nếu có nhiều thao tác dữ liệu được thực thi trong một transaction, bạn phải đánh dấu chắc chắn cho từng công việc. Bạn phải start transaction, và ở 1 vài thời điểm, phải commit những thay đổi. Nếu có lỗi xảy ra (trong quá trình thực thi các thao tác hay trong lúc đang commit những thay đổi), bạn phải roll back transaction để đưa dữ liệu trở về tình trạng thích hợp. Việc này còn được gọi là transaction demarcation.
• Minh họa: tình trạng trong quá trình của một transaction
1.7.2. JDBC và JTA transactions
• Trong môi trường non-managed, JDBC API thường đánh dấu các giao tác. Bạn bắt đầu một transaction bằng cách gọi setAutoCommit(false) trong JDBC connection và kết thúc nó bằng cách gọi commit(). Đôi khi, bạn muốn ép nó rollback ngay lập tức thì có thể làm bằng cách gọi rollback().
• Trong hệ thống lưu trữ dữ liệu trên nhiều cơ sở dữ liệu, một công việc có thể truy cập đến nhiều hơn 1 kho dữ liệu. Trong trường hợp này, bạn không thể chỉ sử dụng JDBC một mình. Bạn cần phải có một transaction manager mà hỗ trợ transaction phân bố. Bạn có thể liên lạc với transaction manager bằng cách sử dụng JTA.
• Trong môi trường managed, JTA không chỉ sử dụng cho transaction phân bố mà còn sử dụng cho container managed transactions (CMT). CMT cho phép bạn ngăn ngừa được những transaction gọi trong source code của ứng dụng.
• Hibernate tác động tới database thông qua JDBC Connection. Vì thế nó hỗ trợ cả APIs. Trong một ứng dụng đơn lẻ, chỉ cần JDBC transaction là đủ, còn trong một ứng dụng server thì Hibernate có thể sử dụng JTA transaction. Như vậy, code Hibernate giổng cả 2 môi trường managed và non-managed. Hibernate cung cấn nhựng lớp trừu tượng bên của nó, được dấu bên dưới transaction API. Hibernate cho phép người sử dụng mở rộng bằng cách đưa thêm vào CORBA transaction service.
1.7.3. Hibernate Transaction API
• Transaction interface cung cấp những phương thức cho một database transaction. Xem ví dụ cơ bản dưới đây:
• Việc gọi session.beginTransaction() là đánh dấu điểm bắt đầu của một một database transaction. Trong trường hợp là môi trường non-managed thì JDBC transaction sẽ bắt đầu trên JDBC connection. Còn trong môi trường managed, nó sẽ bắt đầu một JTA transaction mới nếu chưa có tồn tại JTA transaction, hoặc là kết hợp với JTA transaction đã tồn tại. Tất cả việc này đều được quản lý bởi Hibernate, nên bạn không cần phải quan tâm đến vấn đền này.
• Việc gọi tx.commit() đồng thời thay đổi tình trạng Session đối với cơ sở dữ liệu. Hibernate sẽ commit transaction bên dưới khi và chỉ khi beginTransaction() bắt đầu một transaction mới. Nếu beginTransaction() không bắt đầu một transaction bên dưới mới, commit() chỉ thay đởi tình trạng Session đối với cơ sở dữ liệu.
• Nếu concludeAuction() ném ra một ngoại lệ, chúng ta phải ép buộc transaction rollback bằng cách gọi tx.rollback(). 1.8. Mối kết hợp (Association)
Có 2 mối kết hợp thường được sử dụng. Đó là many-to-one và one-to-many. (còn lại rất hiếm được sử dụng, đó là one-to-one và many-to-many).
1.8.1.
Có những thuộc tính và thẻ con sau:
• Child “column”: chứa tên thuộc tính để chỉ ra cái trường trong CSDL mà chứa khóa ngoại. • Attribute “name”: tên của bảng trong CSDL mà được tham chiếu đến. • Attribute “class”: đối tượng tương ứng của bảng trong CSDL mà được tham chiếu đến. • Attribute “lazy”: nếu được set là true, nạp những đối tượng có liên quan từ CSDL mỗi lần nạp đối tượng này.
1.8.2.
Để chỉ ra quan hệ one-to-many, ta không chỉ đưa ra thẻ one-to-many. Mà còn có những thức khác để làm:
• Đầu tiên, ta phải sử dụng thẻ . Lớp tương ứng trong Java là Set. Ta sử dụng đối tượng này để giữ những giá trị của bảng tham chiểu đến bảng này. • Trong thẻ này, ta phải chỉ ra các thuộc tính và các thẻ con sau:
Attribute “name”: tên của bảng tham chiếu đến bảng này. Attribute “lazy”: nếu được set là true, nạp đối tượng liên quan từ CSDL mỗi lần nạp đối tượng này. Child “key”: có thẻ con là column mà thuộc tính name của nó chứa cái tên của trường chứa khóa ngoại của bảng mà giữ cái id của bảng này. Child “one-to-many”: chứa thuộc tính class để chỉ ra lớp tương ứng của bảng ngoại. 1.9. Simple Queries
1.9.1. HQL (Hibernate Query Language)
1.9.1.1. Tạo thể hiện
Để tạo một thể hiện của HQL, sử dụng session.createQuery(String)
1.9.1.2. Simple query
Ví dụ 1:
//get all records in table User. Query query = session.createQuery("from User")
Ví dụ 2:
Query query = session.createQuery("from User u where u.name = :name"); query.setString("name", "THUAN");
Chú ý rằng User không phải là tên của bảng trong cơ sở dữ liệu. “User” là tên của đối tượng tương ứng với bảng đó. Và tên của những đối tượng này có phân biệt chữ hoa và chữ thường.
1.9.1.3. Kết bảng trong HQL
Một User chứa 1 tập hợp billings (có thuộc tính billings với accessor của nó). Trong mỗi billing, ta có 1 amount (số lượng). Bây giờ, ta muốn lấy tất cả User mà có billing chứa amount lớn hơn 100. Ta sử dũng HQL sau đây:
Query query = session.createQuery("from User user left join fetch user.billings billing where billing.amount > 100");
Chú ý rằng “billings” là tên của một thuộc tính trong cách thuộc tính của “User”. Và nó cũng có một getter và một setter cho billings.
1.9.1.4. Sub-query trong HQL
Ta muốn liệt ke toàn bộ user mà có billing (một vài user có thể không có billings). Ta sử dụng HQL sau đây:
Query query = session.createQuery("from User user where user in (select b.user from Billing B)");
Hoặc:
Query query = session.createQuery("from User user where exists (select 1 from user.billings)");
Chú ý rằng, sub-query trả về nhiều dòng. HQL cũng định nghĩa một số từ khóa để thu hẹp kết quả như: “in”, “all”, “any”, “some”.
1.9.1.5. Gom nhóm
Ví dụ:
Query query = session.createQuery("select count(*) from User"); Query query = session.createQuery("select b.user, sum(b.amount) from Billing b group by b.user");
1.9.2. Điều kiện (Criteria)
1.9.2.1. Tạo thể hiện
Để tạo một thể hiện của Criteria, sử dụng: session.createCriteria(User.class)
1.9.2.2. Add(Criterion)
Tìm trong trong các điều kiện, sử dụng phương thức: add(Criterion)
Ví dụ 1:
Criteria crit = session.createCriteria(User.class); crit.add(Restrictions.eq("name", "Thuan"); //tìm user có name = 'Thuan'
Những phương thức dưới đây dùng để giới hạn tìm kiếm:
eq(String colName, String value): equal gt(String colName, String value): greater than ge(String colName, String value): greater than or equal
và …
Ví dụ: 2: lấy tất cả billing mà có amount nhỏ hơn 100 hoặc lớn hơn 1000
Sử dụng điều kiện “and” bằng cách tương tự như trên.
1.9.2.3. Kết
Ví dụ dưới đây sẽ lấy tất cả Users (và Billings của họ) mà có amount (của billing) lớn hơn 100.
Criteria crit = session.createCriteria(User.class); crit.createCriteria("billings", "bill"); crit.add(Restrictions.gt("bill.amount", new Integer(100));
1.9.3. SQL
1.9.3.1. Tạo thể hiện
Đề tạo một thể hiện của SQL Query, sử dụng: session.createSQLQuery(String).addEntity(String)
Ví dụ:
Query query = session.createSQLQuery("select * from User").addEntity(User.class);
1.9.3.2. SQLGrammaException
Nếu ta chỉ chọn từ User nhưng ta addEntity khác (ví dụ như Billing), Ngoại lệ SQLGrammaException sẽ được ném ra.
Ví dụ:
//SQLGrammaExeption will be thrown in the following code Query query = session.createSQLQuery("select * from User").addEntity(User.class).addEntity(Billing.class);
1.9.3.3. Chọn nhiều bảng, chỉ addEntity một bảng
Nếu ta chọn từ nhiều bảng nhưng ta chỉ addEntity một bảng. Kiểu dữ liệu trả về chỉ là Entity đó.
Ví dụ:
Query query = session.createSQLQuery("select * from Billing b left join User u on u.ID = b.userID").addEntity(User.class); //this query will return a List of User class.
1.9.3.4. Chọn nhiều bản, addEntity nhiều hơn 1 bảng
Nếu ta chọn từ nhiều bảng và ta addEntity nhiều hơn 1 bảng. Kiểu dữ liệu trả về là một mảng đối tượng chứa class theo thứ tự được add.
Ví dụ:
Query query = session.createSQLQuery("select * from Billing b left join User u on u.ID = b.userID") .addEntity(User.class) .addEntity(Billing.class); Iterator iterator = query.list().iterator(); Object[] array; User user; Billing billing; While (iterator.hasNext()) { array = (Object[]) iterator.next(); User user = (User) array[0]; Billing billing = (Billing) array[1]; System.out.println("UserID = " + user.getId() + "; BillingID = " + billing.getId()); }
1.9.3.5. Gom nhóm
Ví dụ:
Query query = session.createSQLQuery("select count(1) userCount from User") .addScalar("userCount", Hibernate.Integer);
Query query = session.createSQLQuery("select u.*, sum(b.amount) sumAmount from Billing b left join User u on u.ID = b.userID group by u.id") .addEntity(User.class) .addScalar("sumAmount", Hibernate.Integer);
Kiểu dữ liệu trả về là danh sách Object[2]. Object[0] là giá trị của phương thức addScalar method, kế tiếp là giá trị của phương thức addEntity.
1.9.4. Giới hạn kết quả trả về
Để giới hạn kết quả trả về, ta sử dụng 2 phương thức: setMaxResults(int) và setFirstResult(int). 2 phương thức này đều được thi hành bởi Criteria và Query 2.1. Khái niệm bean trong Spring
2.1.1. Cách khai báo 1 bean
• Bắt đầu trong spring là bằng thẻ và kết thúc bằng . Để định nghĩa 1 bean, ta dùng tag sau:
Singleton cho biết bean này chỉ được khởi tạo lên 1 lần. Mặc định singleton="true" (vì phần lớn controller chỉ cần khởi tạo 1 lần).
2.1.2. và
• Ta có thể dùng tag property để set giá trị cho attribute của lớp và dùng tag contructor-arg để chỉ định contructor mà mình muốn dùng.
• Ví dụ, ta có class MyBean như sau:
package mypring; public class MyBean { private int myInt; private List myList; public MyBean(int myInt) { this.myInt = myInt; } public void setMyInt(int myInt) { this.myInt = myInt; } public int getMyInt() { return this.myInt; } public void setMyList(List myList) { this.myList = myList; } public List getMyList() { return this.myList; } }
• Ta sẽ khai báo bean như sau:
1
2
red blue
2.1.3.
• Một bean cũng có thể chứa bean khác bằng cách dùng tag ref:
IT - Bài viết Có lẽ bạn đã nghe nói nhiều về Hibernate framework? Thế Hibernate framework là gì? Hy vọng mình và bạn sẽ có trả lời câu hỏi đó khi đọc xong những dòng bên dưới.
Trước khi tìm hiểu Hibernate là gì, chúng ta cần chuẩn bị một số kiến thức để làm nền tảng. Đầu tiên, chúng ta cần tìm hiểu "framework" là gì? Framework ngày nay được "lạm dụng" rất nhiều. Nhiều người hay gán một vài thứ là "framework" nhưng gán gọi như vậy có đúng không lại là một chuyện khác. Theo cộng đồng wikipedia, từ framework dùng trong phát triển phần mềm là một khái niệm dùng để chỉ những "cấu trúc hỗ trợ được định nghĩa" mà trong đó những dự án phần mềm khác có thể được sắp xếp vào đó và phát triển. Thông thường, một framework bao gồm những program hỗ trợ, code libs và một ngôn ngữ scripting nằm giữa các chương trình phần mềm khác để giúp phát triển và gắn những thành phần khác nhau trong dự án phần mềm lại với nhau. Tiếp theo, chúng ta cần tìm hiểu về "persistence layer". Từ này tạm thời mình chưa thể dịch sang tiếng Việt được mà chỉ giải thích để bạn hiểu nó là cái gì thôi. Như bạn đã biết, kiến trúc ứng dụng dụng phần mềm có nhiều loại. Có loại chỉ chạy trên một máy là đủ. Có chương trình muốn chạy được phải kết nối sang một máy khác (client-server). Một máy đóng vai trò như là người yêu cầu (client) và máy khác đóng vai trò kẻ phục vụ (server). Người ta sử dụng thuật ngữ "tier" để chỉ mỗi loại máy có vai trò khác nhau đó. Tier client để chỉ các máy đóng vai trò client và tier server để chỉ các máy đóng vai trò server. Và loại ứng dụng client-server là ứng dụng 2-tier (vì chỉ có 2 tier thôi). Tương tự như vậy theo sự phát triển như vũ bão của công nghệ phần cứng và phần mềm cộng với nhu cầu của các người dùng, doanh nghiệp và xã hội ngày càng lớn, chúng ta thấy có các ứng dụng 3-tier và n-tier để khắc phục nhược điểm của ứng dụng 2-tier và nhằm tăng sức mạnh xử lý cho ứng dụng. "Layer" là một khái niệm khác với "tier". Và chúng ta đừng lầm lẫn giữa "tier" và "layer". Tier thường gắn với phần cứng máy tính (về mặt physically) còn "layer" thì dính với vấn đề cách thức tổ chức bên trong của ứng dụng. Việc phân chia tier là "trong suốt" (transparent) đối với ứng dụng xét về mặt luận lý (logically). Điều này có nghĩa là khi chúng ta phát triển một ứng dụng, chúng ta không bận tâm đến các thành phần (component) sẽ triển khai (deploy) ra sao mà chỉ chú ý là chúng ta sẽ tổ chức ứng dụng thành những layer như thế nào. Ví dụ, một ứng dụng có thể chia làm 3 phần như sau: phần giao diện người dùng (UI layer), phần xử lý nghiệp vụ (business layer) và phần chứa dữ liệu (data layer). Cụ thể ra, business layer sẽ có thể chia nhỏ thành 2 layer con là business logic layer (chỉ quan tâm đến ý nghĩa của các nghiệp vụ, các tính toán mang nhằm thoả mãn yêu cầu của người dùng) và persitence layer. Persistence layer chịu trách nhiệm giao tiếp với data layer (thường là một hệ quản trị cơ sở dữ liệu quan hệ - Relational DBMS). Persistence layer sẽ đảm nhiệm các nhiệm vụ mở kết nối, truy xuất và lưu trữ dữ liệu vào các Relational DBMS.
Việc phân chia như vậy có lợi ích là công việc sẽ được tách bạch ra. Người nào lo thiết kế và xử lý UI thì chỉ việc chú tâm vào công việc đó. Người lo business layer thì chỉ cần tập trung vào thiết kế và phát triển làm sao thoả mãn các requirement của khách hàng mà không phải chú tâm đến các khía cạnh hiện thực bên dưới thông thường liên quan đến technical issues. Còn người lo persistence layer thì chỉ việc chú trọng đến các khía cạnh hiện thực và giải quyết các technical issues mà thôi. Cũng như sẽ có những DBA (DB Administrators) lo việc cài đặt và tạo các objects trong các relational database.
Như vậy, bạn đã hiểu ứng dụng được chia một cách logically thành các "layer" và bạn cũng hiểu được là persistence layer là một layer có nhiệm vụ kết nối Relational DBMSs và truy xuất, thao tác trên dữ liệu đã được lưu trữ cũng như lưu trữ dữ liệu mới vào chúng. Hibernate framework là một framework cho persistence layer. Và bạn có thể thấy rằng nhờ có Hibernate framework mà giờ đây khi bạn phát triển một ứng dụng bạn chỉ còn chú tâm vào những layer khác mà không phải bận tâm nhiều về persistence layer nữa. Tương tự như vậy nếu bạn có một UI framework, bạn sẽ không phải bận tâm nhiều về UI layer nữa. Và xét đến cùng, việc bạn quan tâm duy nhất là business logic layer của bạn có đáp ứng yêu cầu của khách hàng không hay thôi.
Và đây là thông tin về Hibernate framework từ website chính thức của Hibernate: Hibernate là một dịch vụ lưu trữ và truy vấn dữ liệu quan hệ mạnh mẽ và nhanh. Hibernate giúp bạn phát triển các class dùng để lưu trữ dữ liệu theo cách thức rất là hướng đối tượng: association, inheritance, polymorphism, composition và collections. Hibernate cho phép bạn thực hiện các câu truy vấn dữ liệu bằng cách sử dụng ngôn ngữ SQL mở rộng của Hibernate (HQL) hoặc là ngôn ngữ SQL nguyên thuỷ cũng như là sử dụng các API.
Không giống như các persistence layer khác, Hibernate không ẩn đi sức mạnh của ngôn ngữ SQL khỏi bạn mà Hibernate còn đảm bảo cho bạn việc bạn đầu tư vào công nghệ và tri thức cơ sở dữ liệu quan hệ là luôn luôn chính xác. Và điều quan trọng hơn nữa là Hibernate được license theo LGPL (Lesser GNU Public License). Theo đó, bạn có thể thoải mái sử dụng Hibernate trong các dự án open source hoặc các dự án thương mại (commercial).
Hibernate là một dự án open source chuyên nghiệp và là một thành phần cốt tuỷ của bộ sản phẩm JBoss Enterprise Middleware System (JEMS). JBoss, như chúng ta đã biết là một đơn vị của Red Hat, chuyên cung cấp các dịch vụ 24x7 về hỗ trợ chuyên nghiệp, tư vấn và huyấn luyện sẵn sàng hỗ trợ bạn trong việc dùng Hibernate.
Các thành phần của Hibernate project:
* Hibernate Core: Cung cấp các chức năng cơ bản của một persistence layer cho các ứng dụng Java với các APIs và hỗ trợ XML mapping metadata. * Hibernate Annotations: Các map class với JDK 5.0 annotations, bao gồm Hibernate Validator. * Hibernate EntityManager: Sử dụng EJB 3.0 EntityManager API trong JSE hoặc với bất kỳ JEE server nào. * Hibernate Tools: Các tool tích hợp với Eclipse và Ant dùng cho việc sinh ra các persistence object từ một schema có sẵn trong database (reverse-engineering) và từ các file hbm sinh ra các class java để hiện thực các persistence object, rồi Hibernate tự tạo các object trong database (forward-engineering). * NHibernate: Hibernate cho .Net framework. * JBoss Seam: Một Java EE 5.0 framework cho phát triển các ứng dụng JSF, Ajax và EJB 3.0 với sự hỗ trợ của Hibernate. Seam hiện rất mới và tỏ ra rất mạnh để phát triển các ứng dụng Web 2.0. Nó tích hợp đầy đủ tất cả các công nghệ "hot" nhất hiện nay.
Theo : http://my.opera.com/mattroiden3012/blog/tong-quan-hibernate-framework