Thứ Tư, 7 tháng 3, 2012

Tìm hiểu Hibernate

Chương 1.
Tìm hiểu Hibernate
Hibernate là một framework được một cậu sinh viên ở Châu Âu (anh ko nhớ nước nào) nghĩ ra để đơn giản hóa , tự động hóa quá trình kết nối và thao tác trên CSDL
dựa vào những cấu trúc định nghĩa bằng file .xml để thực hiện việc tạo CSDL, bảng, các ràng buộc trên bảng, các quan hệ tham chiếu ...
có nghĩa là việc kết nối tới csdl khi dùng hibernate giúp người lập trình ít quan tâm hơn tới việc thao tác trên dữ liệu mà quan tâm tới những ràng buộc dữ liệu nhiều hơn, thông qua các annotation được định nghĩa, làm cho việc thao tác CSDL hướng đối tượng hoàn toàn

tóm lại là dùng hibernate là dùng các file config và các lớp liên kết để tạo CSDL chứ ko dùng tay hay lớp DAO bình thường

1.1. Khái niệm Hibernate

1.1.1. ORM Framework

• 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.

Re:Hibernate Framework và mô hình MVC cách đây 2 năm, 10 tháng #1512

  • langtujava
  • không trực tuyến
  • Expert Boarder
  • Tổng số bài viết: 112
  • Điểm khen ngợi: 0
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ẻ <hibernate-configuration> và kết thúc với thẻ </hibernate-configuration>.

• Thẻ <session-factory> là thẻ con của thẻ <hibernate-configuration>. Những thể con của thẻ <session-factory> đượ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ẻ <property name=””>class</property>.

§ 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ụ:
<property name=”hibernate.connection.driver_class”>
com.mysql.jdbc.Driver
< /property>

• Để định nghĩa resouces của session-factory, ta sử dụng <mapping resource=””/>

§ 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.1. Cấu trúc cơ bản
• Bắt đầu bằng <hibernate-mapping> và kết thúc với </hibernate-mapping>.

• Từng bảng trong CSDL được đinh nghĩa bằng thẻ <class> 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ẻ <class> có các thẻ con sau:

§ Thẻ <id>: để đị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ẻ <id> cũng có thẻ con sau:
o Thẻ <generator class=””> để 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ẻ§ <property> để chỉ ra một cột bình thường, có cùng thuộc tính như thẻ <id> ngoại trừ việc thẻ này không có thẻ con <generator>.

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.4.2.1. Java primitive mapping types



• Bạn cũng nên chú ý rằng cơ sở dữ liệu của bạn có thể sẽ không hỗ trợ một vài SQL types ở trên. Danh sách ở trên chỉ là ANSI-standard data types.

• Tuy nhiện, JDBC driver cung cấp vendor-specific SQL data types, cho phép Hibernate làm việc với ANSI-standard types khi thực thi câu lệnh DML (data manipulation language). Đối với DDL, Hibernate dịch ANSI-standard type thành vendor-specific type bằng cách sử dụng đặc tả SQL dialects.

1.4.2.2. Date – time mapping types



1.4.2.3. Large object mapping types



• java.sql.Blob và java.sql.Clob là cách hiểu quả nhất để quản lý large object trong Java.

• Tuy nhiên, do hạn chế là Blob và Clob chỉ có thể sử dụng cho đến khi JDBC transaction hoàn tất, nên người ta thường sử dụng binary hay text mapping type.

• Chú ý: bạn có thể kiếm cái mẫu mới nhất (design pattern) và hướng dẫn sử dụng large object trên website của Hibernate.

1.4.2.4. Various JDK mapping type



1.4.2.5. Sử dụng mapping types
< class
name="vn.huflit.diendan.model.Forum"
table="FORUM"
>
< id
name="id"
type="java.lang.Long"
unsave-value="null"
>
< column
name="FORUM_ID"
not-null="true"
sql-type="INTEGER"
/>
< generator class="identity">
< /generator>
< /id>

< property
name="forumSubject"
type="java.lang.String"
update="true"
insert="true"
>
< column
name="FORUM_SUBJECT"
not-null="true"
sql-type="VARCHAR(50)"
/>
< /property>

< !—
Tiep tuc...
-->

< /class>


1.4.3. Mapping collection of value types (sử dụng bag)



• Trong trường hợp ta có CSDL như trên, một FORUM thuộc một CAT và một CAT có nhiều FORUM.
• Vậy nên, trong CAT có danh sách FORUM, như vậy trong Class Category có một thuộc tính forumList, và ta sẽ ánh xạ forumList như thế nào.
• Ta sẽ sử dụng thẻ bag để làm công việc này trong tập tin mapping của CAT:
< bag
name="forumList"
lazy="true"
cascade="save-update"
>
< key
column="CAT_ID"
>
< /key>

< one-to-many
class="vn.huflit.diendan.model.Forum"
/>
< /bag>


1.4.4. Mapping Entity Association

Thường có 4 dạng kết hợp là: one-to-one, many-to-many, one-to-many, many-to-one, nhưng thường thì ta chỉ sử dụng 2 loại kết hợp: one-to-many và many-to-one.

1.4.4.1. One-to-many



• Như ví dụ phần trên, một FORUM thuộc một CAT và một CAT chứa nhiều FORUM, nên trong CAT có thuộc tính forumList.
• Đối với mỗi phần tử trong forumList sẽ thuộc một CAT, vì vậy, quan hệ giữa CAT với những phần tử này là one-to-many.
• Ta dùng thẻ <one-to-many> nằm trong lớp Category (trong thẻ bag) để cho biết Category có nhiều phần tử nằm trong forumList và mỗi phần tử đó chính là một thể hiện của Forum.
• Ví dụ (xem phần Mapping collection of value types)

1.4.4.2. many-to-one



• Để thể hiện rằng một TOPIC thuộc một FORUM, và cũng có thể một thể hiện khác của TOPIC cũng thuộc FORUM trên, ta sẽ sử dụng thể <many-to-one> trong tập tin ánh xạ của TOPIC.
• Ví dụ:
<many-to-one
name="forumId"
class="vn.huflit.diendan.model.Forum"
cascade="none"
outer-join="auto"
update="true"
insert="true"
>
< column
name="FORUM_ID"
not-null="true"
sql-type="INTEGER"
/>
< /many-to-one>


1.4.5. Cascading action

• Về các thuộc tính cascade trong các thẻ bên trên, ý nghĩa nó tương tự như các tùy chọn cascade trong các hệ quản trị CSDL mà ta đã từng biết như Ms Access, SQL Server, Oracle, ... Các giá trị của cascade:
§ "none": không thực hiện gì cả, tự ta kiểm tra các ràng buộc và thực hiện cho đúng để tránh ngoại lệ.
§ "save-update": lưu và cập nhật cha sẽ được cập nhật cả con.
§ "delete": xóa cha thì sẽ thực hiện xỏa cả con.
§ "all": tất cả hành động bao gồm "save-update" hay "delete" đều được thay đổi con nếu có thay đổi từ cha.
§ "all-delete-orphan": tất cả hành động sẽ được cập nhật từ cha đến con, những con không còn cha sẽ bị xóa.
• Thường thì, save-update là một lựa chọn tốt nhất và dễ xài.

Re:Hibernate Framework và mô hình MVC cách đây 2 năm, 10 tháng #1513

  • langtujava
  • không trực tuyến
  • Expert Boarder
  • Tổng số bài viết: 112
  • Điểm khen ngợi: 0
Phần Tiếp Theo

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();

//
//do sth with session here
//

//commit
tx.commit();
//close session
session.close();


1.6.2. Rút trích một persistence object bằng id

Ví dụ lấy ra một user bằng id:
User user = session.get(User.class,newLong(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,newLong(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

Session session2 = sessionFactory.openSession(); //another session
session2.lock(user, LockMode.NONE); //reassociated


1.6.4. Updating persistence objects

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 =newUser();
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 =newUser();
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:
Session session = session.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();

concludeAuction();

tx.commit();
} catch (Exception e) {
if (tx != null) {
try {
tx.rollback();
} catch (HibernateException he) {
// log he and rethrow e
}
}
throw e;
} finally {
try {
session.close();
} catch (HibernateException he) {
throw he;
}
}


• 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().
Trả Lời Với Trích Dẫn

Re:Hibernate Framework và mô hình MVC cách đây 2 năm, 10 tháng #1514

  • langtujava
  • không trực tuyến
  • Expert Boarder
  • Tổng số bài viết: 112
  • Điểm khen ngợi: 0
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. <many-to-one>

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. <one-to-many>

Để 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ẻ <set>. 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
Criteria crit = session.createCriteria(Billing.class);
Crit.add(Restrictions.or(
Restrictions.lt("amount", 100),
Restrictions.gt("amount", 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.cla ss);


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

Không có nhận xét nào:

Đăng nhận xét