hibernate

61
Báo cáo đề tài tìm hiểu Hibernate-phần 1 Báo cáo tìm hiểu đề tài – mã đề tài: SE04. HIBERNATE – phần 1 I. Component mapping. 1. Component mapping là gi? Component không phải là một tham chiếu thực thể, nó giống như một đối tượng được chứa trong một đối tượng cha khác. Nó không có id và chỉ tồn tại khi thực thể cha tồn tại. Component cho phép bạn nhóm một vài cột vào trong một đối tượng. Ta xét ví dụ: 1041349 - 1041397 - 1041444 Page 1

Upload: happybear

Post on 22-Sep-2014

431 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Báo cáo tìm hiểu đề tài – mã đề tài: SE04.

HIBERNATE – phần 1

I. Component mapping.

1. Component mapping là gi?Component không phải là một tham chiếu thực thể, nó giống như một đối tượng được chứa trong một đối tượng cha khác. Nó không có id và chỉ tồn tại khi thực thể cha tồn tại. Component cho phép bạn nhóm một vài cột vào trong một đối tượng.Ta xét ví dụ:

Ta quan sát, bảng AccountOwner gồm các thuộc tính:- accountOwner- lastname- firstname- socialSecuritynumber- streeAddress

1041349 - 1041397 - 1041444 Page 1

Page 2: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

- city- state- zip-code- home-phone- cell-phone

để tổ chức cơ sở dữ liệu tốt hơn, người ta sẽ tách các thuộc tính : StreetAddress, city, zipcode ra thành một đơn vị dữ liệu riêng, việc này giúp cơ sở dữ liệu của chúng ta tường minh hơn, rõ ràng hơn và việc truy xuất đơn giản hơn.

Các thuộc tính sau khi được tách ra sẽ thuộc về 1 đơn vị dữ liệu có tên là Address.Ta có nhận xét như sau:- Address được chứa trong AccountOwner- Address chỉ tồn tại khi AccountOwner tồn tại

Nói một cách khác, Address chính là một component.

2. Using Component - sử dụng componentViệc ánh xạ từ bảng dữ liệu cho component là hết sức đơn giản. để dễ hiểu hơn, ta xét việc ánh xạ từ bảng AccountOwner cho component address như sau:

1041349 - 1041397 - 1041444 Page 2

Page 3: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Cú pháp của một component như sau: Bên trong thẻ component là thẻ parent khai báo tên của Cha.Tiếp theo là các thẻ property khai báo các thuộc tính bên trong của component.

3. Nested Components - Component lồng nhau:Là hiện tượng bên trong component cho có chứa các component con bên trong.Xét ví dụ sau:

1041349 - 1041397 - 1041444 Page 3

Page 4: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Thuộc tính zipcode được chia làm hai phần: Zip và plus4. Ví du: 12222-1234.Như vậy để thuận tiện, người ta đưa zipcode vào một component như hình sau:

Ta thấy được rằng bên trong bảng AccountOwner có component Address và bên trong Address có component Zipcode. Đây là một ví dụ điển hình cho việc thể hiện Nested component.Ta biểu diễn file mapping như sau:

1041349 - 1041397 - 1041444 Page 4

Page 5: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

4. Mapping a component – Tham chiếu trong componentMột component có thể có tham chiếu tới đối tượng <parent>.

5. Collection of component

1041349 - 1041397 - 1041444 Page 5

Page 6: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

6. Component as Entity ID

II. Collection Mapping

1. Mapping collection of valueTập hợp các giá trị: là danh sách lưu trữ các giá trị, các kiểu tham trị(String, integer,double…) nhưng không phải là đối tượng cố định.Mapping collection of value là sự tập hợp của các giá trị.Để định nghĩa tập hợp, ta sử dụng thẻ <bag>, 1 thẻ tập hợp đơn giản trong hibernat.Thẻ <bag> là đối tượng không theo thứ tự, mỗi cái có thể chứa các phần tử lặp lại.Ví dụ về thẻ <bag>:

2. Collection types in hibernateNgoài thẻ <bag> , còn có nhiều tập hợp khác trong hibernate, mỗi loại có những ưu điểm và đặc điểm riêng.2.1. Association as <bag>

Thẻ <bag> là một tập hợp mà trong đó, nó có thể chứa các phần tử tập hợp.Thẻ <bag> thực hiện thông qua Collection hoặc List.Thẻ <bag> yêu cầu phải có cột giá trị, có thể sắp xếp tăng giảm.

1041349 - 1041397 - 1041444 Page 6

Page 7: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Thẻ <bag> được sử dụng trong quan hệ one-many hoặc many-one.Vi dụ về khai báo thẻ <bag>:

2.2. Association as <Set>Thẻ <set>tương tự như thẻ <bag> nhưng không chưa các phần tử lặp lại.Có thể có thứ tự hoặc không có thứ tự, nhưng đòi hỏi phải có cột giá trị.Thẻ <Set> có thể tùy chọn sắp xếp : unsort hoặc natural.Thẻ <Set> được sử dụng trong quan hệ one-many hoặc many-one.Ví dụ về khai báo thẻ <Set>:

2.3. Association as <List>Thẻ <List> là tập hợp chỉ mục được kết nối, chúng ta có thể giữ lại thứ tự của list khi nó kết nối lại, do đó nó cần phải có một chỉ mục của cột mà nó tham chiếu tới trong bảng cơ sở dữ liệu.<List>khác <Bag> là <List> có kết nối chỉ mục phần tử.Thẻ <List> được sử dụng trong quan hệ one-many hoặc many-one.Ví dụ về khai báo thẻ <List> :

2.4. Association as <Array>

1041349 - 1041397 - 1041444 Page 7

Page 8: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Thẻ <Array> tương đối giống thẻ <List>, có một điểm khác biệt đó là thẻ <Array> tương ứng với kiểu mảng trong java, còn thẻ <List >tương ứng với kiểu List.Do đó, khi mảng không thể tự động tăng giảm được kích thước, người ta thường sử dụng thẻ<List>.Thẻ <Array> được sử dụng trong quan hệ one-many hoặc many-oneVí dụ về khai báo thẻ <Array>:

2.5. Association as MapThẻ <map> gần giống như thẻ <List> nhưng thẻ <map> sử dụng khóa có kiểu bất kỳ để làm chỉ mục chứ không sử dụng kiểu int như thẻ <List>.Thẻ <map> có thể có thứ tự hoặc không có thứ tự nhưng đòi hỏi phải có khóa và giá trị cột.Thẻ <map> được sử dụng trong quan hệ one-many hoặc many-oneVí dụ về khai báo thẻ <map>:

2.6. Association as idbagThẻ <idbag> sử dụng tương tự như thẻ <bag> nhưng nó thêm khả năng nhận dạng thêm các key thay thế.Không thể sử dụng thẻ<idbag > cho cả 2 mặt của quan hệ(many-many).Thẻ <idbag> được sử dụng trong quan hệ many-many.Ví dụ về khai báo thẻ <idbag>:

1041349 - 1041397 - 1041444 Page 8

Page 9: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

3. Sorting the collection.

3.1. Sorting database.Khi tập hợp quá lớn, để sắp xếp thuận lợi nhất, ta sắp xếp tập hợp trong cơ sở dữ liệu.Để sắp xếp, ta sử dụng từ khóa orderby, với 2 giá trị có thể lựa chọn, đó là asc (sắp tăng) và desc(sắp giảm). Chúng ta cần chú ý một điều là thuộc tính orderby không phải là một thuộc tính trong hibernate mà chỉ là một cột trong cơ sở dữ liệu.

3.2. Sorting memoryKhi kích thước không lớn, ta có thể sử dụng phương pháp sắp xếp này. Và điều đặc biệt của việc sắp xếp này đó là chỉ có thẻ <map> và thẻ <set> là có thể sử dụng được.Để sắp tăng ta khai báo từ khóa sort với ba giá trị là natural, unsort, hoặc my.custom.mycomparator.

III. Inheritance Mapping.(Tính kế thừa trong Hibernate)

Đặc tính của Kế thừa (Inheritance)

- Dễ sử dụng trong ngôn ngữ hướng đói tượng(object oriented language).

Java: sử dụng từ khóa “extend” hay “implement”.

- Nhưng lại không dễ sử dụng trong dữ liệu quan hệ.

Các bảng không thể “extend” từ các bảng khác được.

Vấn đề “Impedence missmatch”.

Để hiểu rõ vấn đề Impedence missmatch ta xem ví dụ sau :

 Ta có một mô hình dữ liệu có 2 table: Customers và Accounts.

1041349 - 1041397 - 1041444 Page 9

Page 10: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Như vậy chúng ta sẽ tạo mô hình object với 2 class tương ứng với 2 table này: 

  

Nhưng mô hình object trên thiếu tính linh động và khả năng mở rộng, do đó chúng ta nên thiết kế lại để thêm inheritance và abstraction, làm mô hình gần hơn với thực tế:

Chúng ta có thể thấy rõ ràng sự không đối xứng (mismatch) giữa mô hình dữ liệu và mô hình object trong trường hợp này. Trong database, hoàn toàn chấp nhận được khi chứa toàn bộ thông tin của Person và PersonName trong một table Customers. Nhưng để tăng tốc độ thực thi, việc bảo trì và sự linh hoạt; một object lớn nên được chia thành nhiều object nhỏ.

Vậy phải giải quyết các vấn đề này như thế nào?

Trong Hibernate ta có 4 cách giải quyết :

1. Table per class hierachy.2. Table per subclass.3. Table per concrete class.4. Đa hình tiềm ẩn.

Xét ví dụ sau đây: Ta có 3 lớp : Person, Teacher và Student. Trong đó Person là lớp cha và Teacher , Student kế thừa từ lớp cha này.

1041349 - 1041397 - 1041444 Page 10

Page 11: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Sơ đồ lớp:

Table per class hierachy.Với phương pháp nà ta sẽ ánh xạ tất cả các lớp vào duy nhất 1 bảng. tất cả các thuộc tính của các lớp sẽ hiển thị trong bảng như là một colum, trong đó sẽ có 1 cột chứa các tên lớp con mà ta gọi là “Discriminator” để phân biệt các lớp với nhau.

 

Theo bảng Person trên ta thấy Discriminator lúc này là cột PERSON_TYPE chứa 2 trường dữ liệu là Sutent và Teacher. Đây là tên của hai lớp con kế thừa từ lớp cha Person.Bảng PERSON chứa tất cả các thuộc tính (attributes ) cùa các lớp Person, Teacher và Student như là các colunms của nó.Mapping cho Table class hierachy:

Person.hbm.xml

<hibernate-mapping> <class name=”Person” table=”PERSON”> <id name=”id” column=”ID”> <generator class=”increment”/> </id> <discriminator column=”PERSON_TYPE” type=”string”/> <property name= “name” column=”NAME”/> </class></hibernate-mapping>

1041349 - 1041397 - 1041444 Page 11

Page 12: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Bảng Person có chứa column PERSON_TYPE. Column này được maped (ánh xạ) bằng cách sử dụng thẻ XML <discriminator> .Discriminator không phải là thuộc tính của bất kỳ java class nào, nó chỉ là một cột được dùng chung giữa databse và Hibernate.

Mapping file cho hai lớp Student và Teacher.

Student.hbm.xml===============

<hibernate-mapping> <subclass name=”Student” extends=Person” discriminator-value=”Student”> <property name= “branch” column=”BRANCH”/> </subclass></hibernate-mapping>

Teacher.hbm.xml===============

<hibernate-mapping> <subclass name=”Teacher” extends=Person” discriminator-value=”Teacher”> <property name= “department” column=”DEPARTMENT”/> </subclass></hibernate-mapping>

Ưu điểm :

Cách tiếp cận này thì đơn giản và hiệu quả vì tất cả các dữ liệu thì đều nằm trong cùng một bảng nên việc kết bảng lúc này thì không cần thiết.

Nhược điểm :không thể khai báo cho các subclass ràng buộc NOT NULL.

Table per concrete class

Một lớp con là một bảng riêng biệt.

1041349 - 1041397 - 1041444 Page 12

Page 13: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Bây giờ ta mapping bằng <union-subclass>

<union-subclass> được sử dụng cho mỗi subclass trong mapping file.

<class name="Person"> <id name="id" type="long" column="ID"> <generator class="sequence"/> </id> <property name="name" column="NAME"/> <union-subclass name="Student" table="STUDENT"> <property name="branch" column="BRANCH"/> </union-subclass> <union-subclass name="Teacher" table="TEACHER "> <property name="branch" column="BRANCH"/> </union-subclass></class>

Table per subclass:

Ta tạo ra ba bảng riêng biệt cho 3 lớp.

1041349 - 1041397 - 1041444 Page 13

Page 14: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<joined-subclass> được sử dụng cho mỗi subclass torng mapping file.

<class name="Person" table="PERSON"> <id name="id” column="ID"> <generator class="native"/> </id> <property name="name" column="NAME"/> <joined-subclass name="Teacher" table="TEACHER"> <key column="ID"/> <property name="department" column="DEPARTMENT"/> </joined-subclass> <joined-subclass name="Student" table="STUDENT"> <key column="ID"/> <property name="branch" column="BRANCH"/> </joined-subclass></class>

Trong trường hợp này ta sẽ có 3 bảng. Và khóa chính của các subclass trùng với khóa chính của lớp cha( Ở đây khóa chính của cả 3 bảng là ID).

IV. Working With Object1. vòng đời của một object trong Hibernate.

Các objects mà Hibernate quản lý phải luôn luôn ở một trong bốn trạng thái(STATE) sau đây:

1041349 - 1041397 - 1041444 Page 14

Page 15: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

1. Transient.2. Persisten.3. Removed.4. Detatched.

Các Objects muốn chuyển từ trạng thái này sang trạng thái khác sẽ được thực hiện thông qua các phương thức khác nhau.

Transient State_ Trạng thái tạm thời.

Tất cả các đối tượng khi mới khởi tạo đều ở trạng thái Transient.

Account account = new Account();

Đối tượng account vừa được ta khởi tạo cho nên account bây giờ đang ở trạng thái tạm thời mà thôi.

Đặc điểm của các đối tượng khi đang ở trạng thái Transient State:

Hibernate không thể nhận ra các đối tượng này . Các đối tượng này không hề có bất kỳ liên quan đến các dữ liệu

có trong database. Do không có giá trị cho accountID.(accountID là khóa chính.) Khi đối tượng mới khởi tạo này không liên quan đến bất kỳ đối

tượng nào khác thì nó sẽ được hủy bởi cơ chế thu gom rác(garbage collected).

PERSISTENT STATE_Trạng thái ổn định .

Với các đối tượng ở trạng thái này thì nó có các đặc điểm sau:

Được nhận biết và chịu sự quản lý của Hibernate. Có một database id

là một đối tượng được tồn tại bằng việc lấy lên từ database. Hay là một đối tượng đang ở trạng thái tạm thời (Transient

State) nhưng đã được lưu. Đây là trạng thái duy nhất mà các objecs được lưu vào database.

Nói cách khác khi một object muốn được lưu vào databse điều đầu tiên là nó phải đang ở trạng thái Persisent.

Việc chỉnh sửa, cập nhật trên một đối tượng đang ở trang thái khác trạng thái này sẽ KHÔNG được lưu lại vào database .

1041349 - 1041397 - 1041444 Page 15

Page 16: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Trong khi đó khi ta làm việc với một đối tượng đang ở trạng thái Persistent thì việc thay đổi của đối tượng này sẽ được tự động cập nhật xuống databse mà không càn gọi bất kỳ phương thức Session Persistent nào.

các đối tượng được tạo ra ổn định , lâu bền thông qua các Hibernate session:

session.save(account); session.update(account); session.lock(account); session.merge(account);

Ta xem ví dụ sau đây:

Đầu tiên ta thấy khi mới khởi tạo đối tượng account thông qua phương thức new Account() thì accoount lúc này đang ở trạng thái tạm thời mà thôi(Transient state). Hibernate không làm việc trên account đơn giản vì nó không hiểu account là gì.

1041349 - 1041397 - 1041444 Page 16

Page 17: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Vậy để Hibernate hiểu và làm việc trên account ta phải chuyển nó về trạng thái Persistent thông qua session . Lúc này việc cập nhật, thay đổi ta làm trên account sẽ được Hibernate tự động lưu xuống databse.

REMOVE STATE.

Xét đối tượng đang ở trạng thái Persistent.

Remove state là trạng thái mà mà đối tượng này đã bị delete ra khỏi database.

session.delete(account);

Lúc này mọi thay đổi trên đối tượng này sẽ không còn được lưu xuống database nữa. Cơ chế thu gom rác của Hibernate sẽ dọn dẹp đối tượng này bởi vì Hibernate không cho phép tồn tại một đối tượng rỗng.(Đối tượng không lưu trử bất kỳ thông tin gì.)

Xét ví dụ sau đây:

Đẩu tiên khởi tạo một phiên làm việc cho Hibernate(session)

Sau đó ta lấy lên một account với id = 1 . Lúc này account được trả ra trong trạng thái Persistent.

Tiếp đó ta tiến hành delete account đi.

1041349 - 1041397 - 1041444 Page 17

Page 18: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Lúc này mọi chỉnh sửa trên account sẽ bị Hibernate lờ đi vì account hiện tại đang ở trạng thái Remove.

Chú ý rằng trong Java thì đối tượng account lúc này sẽ vẫn còn alive, tức là ta có thể gán giá trị cho nó, làm việc với nó như một đối tượng bình thường dù đã bị delete ra khỏi databse và đối tượng này sẽ alive cho đến khi nào lập trình viên set nó null hoặc hủy nó đi.

DETACHED STATE

Một đối tượng persistent sẽ vẫn còn được tham chiếu sau khi session của nó đã đóng lại.

Phương thức session.close() thay đổi trạng thái của đối tượng từ Persistent sang Detached.

Đặc tính:

Đối tượng lúc này vẫn đại diện cho hàng dữ liệu mà nó đang mang trong databse.

Nhưng không thuộc sự quản lý của Hibernate nữa.

Lúc này mọi sự thay đổi trên detached object sẽ không còn được lưu xuống database .

Có thể redetached ( kết nối lại) để trả về trạng thái Persistent cho đối tượng và gây ra hiện tượng là lưu lại trạng thái của chính nó xuống database.

update();

merge();

lock(); // ta retach() nhưng sẽ không lưu trạng thái .

Xét ví dụ sau :

1041349 - 1041397 - 1041444 Page 18

Page 19: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Đầu tiên khởi tạo session1.

Tạo đối tượng account thông qua session1.

Sau đó đóng session1 lại.

Lúc này account đang ở trạng thái Detached State.

Bây giờ ta muốn trả lại trạng thái Persistent cho nó thì ta re-attach lại thông qua việc mở ra một phiên làm việc mới tức là tạo ra session2.

HIBERNATE LIFECYCLE

V. Association Mapping1. Giới thiệu

Trình bày các mối quan hệ thường là điều khó khăn nhất để thể hiện một cách chính xác. Trong phần này, chúng ta xem xét một số trường hợp thông dụng, bắt đầu với mối quan hệ một chiều và sau đó là hai chiều.

1041349 - 1041397 - 1041444 Page 19

Page 20: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

2. Các mối quan hệ thông dụng2.1. Quan hệ một chiều (unidirectional association):

a. Nhiều – Một : Quan hệ Nhiều – Một là loại quan hệ phổ biến nhất trong các mối quan hệ. Mỗi một căn nhà (có địa chỉ) thuộc về một cá nhân, mỗi cá nhân có thể có nhiều căn nhà. Mối quan hệ hướng từ căn nhà ( có địa chỉ ) đến cá nhân là mối quan hệ Nhiều – Một.

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<many-to-one name="address"

column="addressId"

not-null="true"/>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

b. Một – Một : Mối quan hệ một – một giống như mối quan hệ Nhiều – Nhiều nhưng có them thuộc tính Unique = true

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

1041349 - 1041397 - 1041444 Page 20

Page 21: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<many-to-one name="address"

column="addressId"

unique="true"

not-null="true"/>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

Hoặc ta có thể sử dụng cách khác dưới đây

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

</class>

<class name="Address">

<id name="id" column="personId">

<generator class="foreign">

<param name="property">person</param>

</generator>

</id>

<one-to-one name="person" constrained="true"/>

c. Một – Nhiều : Mối quan hệ Một – Nhiều là một mối quan hệ không thông dụng và ít được giới thiệu.

1041349 - 1041397 - 1041444 Page 21

Page 22: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<set name="addresses">

<key column="personId"

not-null="true"/>

<one-to-many class="Address"/>

</set>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

Bạn nên thay thế dùng một bảng tham gia trong trường hợp này.

2.2. Quan hệ một chiều có dùng bảng tham gia :

a. Một - Nhiều : Mối quan hệ Một - Nhiều với bảng tham gia là ưu tiên lựa chọn. Chỉ rõ unique = true đã chuyển từ quan hệ Nhiều – Nhiều sang quan hệ Một - Nhiều.

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<set name="addresses" table="PersonAddress">// bảng tham gia

<key column="personId"/>

1041349 - 1041397 - 1041444 Page 22

Page 23: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<many-to-many column="addressId"

unique="true"

class="Address"/>

</set>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

b. Nhiều – Một : Quan hệ Nhiều – Một với một bảng tham gia là mối quan hệ phổ biến khi mối quan hệ là tuỳ chọn.

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<join table="PersonAddress"

optional="true">// tuỳ chọn

<key column="personId" unique="true"/>

<many-to-one name="address"

column="addressId"

not-null="true"/>

</join>

</class>

<class name="Address">

1041349 - 1041397 - 1041444 Page 23

Page 24: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<id name="id" column="addressId">

<generator class="native"/>

</id>

c. Một – Một : Quan hệ Một – Một với một bảng tham gia là quan hệ có thể sử dụng nhưng chi trong các trường hợp cực kỳ đặc biệt.

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<join table="PersonAddress"

optional="true">

<key column="personId"

unique="true"/>

<many-to-one name="address"

column="addressId"

not-null="true"

unique="true"/>

</join>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

1041349 - 1041397 - 1041444 Page 24

Page 25: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

d. Nhiều – Nhiều : Quan hệ Nhiều - Nhiều có bảng tham gia là một điển hình trong các mối quan hệ

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<set name="addresses" table="PersonAddress">

<key column="personId"/>

<many-to-many column="addressId"

class="Address"/>

</set>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

2.3. Quan hệ hai chiều (bidirectional association) :a. Một – Nhiều / Nhiều – Một : Quan hệ hai chiều Nhiều – Một là

quan hệ phổ biến nhất.

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<many-to-one name="address"

1041349 - 1041397 - 1041444 Page 25

Page 26: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

column="addressId"

not-null="true"/>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

<set name="people" inverse="true">

<key column="addressId"/>

<one-to-many class="Person"/>

</set>

Nếu bạn sử dụng một danh sách, hoặc lập chỉ mục thì thiết lập các cột quan trọng với khoá ngoại không phải null. Hibernate sẽ quản lý các liên kết từ các phía để duy trì chỉ số của mỗi phần tử với thiết lập update = false và insert = false

<class name="Person">

<id name="id"/>

...

<many-to-one name="address"

column="addressId"

not-null="true"

insert="false"

update="false"/>

</class>

1041349 - 1041397 - 1041444 Page 26

Page 27: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<class name="Address">

<id name="id"/>

...

<list name="people">

<key column="addressId" not-null="true"/>

<list-index column="peopleIdx"/>

<one-to-many class="Person"/>

</list>

b. Một – Một : Quan hệ Một – Một hai hướng là quan hệ phổ biến.

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<many-to-one name="address"

column="addressId"

unique="true"

not-null="true"/>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

<one-to-one name="person"

property-ref="address"/>

1041349 - 1041397 - 1041444 Page 27

Page 28: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<one-to-one name="address"/>

</class>

<class name="Address">

<id name="id" column="personId">

<generator class="foreign">

<param name="property">person</param>

</generator>

</id>

<one-to-one name="person"

constrained="true"/>

2.4. Quan hệ hai chiều với bảng tham gia:a. Một – Nhiều / Nhiều – Một :

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<set name="addresses"

table="PersonAddress">

<key column="personId"/>

1041349 - 1041397 - 1041444 Page 28

Page 29: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<many-to-many column="addressId"

unique="true"

class="Address"/>

</set>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

<join table="PersonAddress"

inverse="true"

optional="true">

<key column="addressId"/>

<many-to-one name="person"

column="personId"

not-null="true"/>

</join>

b. Một – Một :

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

</id>

<join table="PersonAddress"

optional="true">

<key column="personId"

1041349 - 1041397 - 1041444 Page 29

Page 30: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

unique="true"/>

<many-to-one name="address"

column="addressId"

not-null="true"

unique="true"/>

</join>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

<join table="PersonAddress"

optional="true"

inverse="true">

<key column="addressId"

unique="true"/>

<many-to-one name="person"

column="personId"

not-null="true"

unique="true"/>

</join>

c. Nhiều – Nhiều :

<class name="Person">

<id name="id" column="personId">

<generator class="native"/>

1041349 - 1041397 - 1041444 Page 30

Page 31: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

</id>

<set name="addresses" table="PersonAddress">

<key column="personId"/>

<many-to-many column="addressId"

class="Address"/>

</set>

</class>

<class name="Address">

<id name="id" column="addressId">

<generator class="native"/>

</id>

<set name="people" inverse="true" table="PersonAddress">

<key column="addressId"/>

<many-to-many column="personId"

class="Person"/>

</set>

VI. Batch processingBatch process là quá trình thực thi cùng một lúc một loạt các chương trình.Trong suốt quá trình thực thi Batch process ta cần thêm xóa sửa một lượng lơn dữ liệu, điều này có thể làm tràn bộ nhớ tạm của Hibernate (Outofmemmory).

Để giải quyết vấn đề này, ta sử dụng phương thức flush() và clear() để xóa bộ nhớ tạm sau mỗi 100 đến 200 dòng dữ liệu.

1041349 - 1041397 - 1041444 Page 31

Page 32: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Hai phương thức này giải phóng bộ nhớ tạm ở mức 1.Ngược lại, nếu bộ nhớ tạm ở mức hai được sử dụng ( Mức Entity), ta phải tắt chức năng này bằng câu lệnh :

Sessesion.setCacheMode(CacheMode.IGNOR)Ở cấp toàn cục, ta có thể thiết lập kích thước mỗi khối xử lý cho JDBC

bằng thuộc tính :jdbc.Batch_Size

Tắt bộ nhớ tạm ở mức hai bằng trong file Mapping bằng cách đặt thuộc tính Cach.use_second_level_cache về false.1. Batch insert

Để thêm 100000 dòng dữ liệu ta làm các việc như sau : Đăng ký phiên làm việc Session. Tiến hành insert dữ liệu. Kiểm tra và dung hai phương thức flush() và Cleart() để xóa bộ

nhớ tạm ở mức một.2. Batch Update –batch Delete

2.1. Sử dụng ScrollSử dụng hai phương thức flush() và clear() để xóa bộ nhớ tạm ở mức một và lưu thành khối.Dùng Scroll để lấy về một JDBC Result (ScrollableResults) và update hoặc Delete từng row.Hiệu chỉnh CacheMode.IGNORE để Hibernate không tương tác với bộ nhớ tạm mức hai trong một session riêng.

1041349 - 1041397 - 1041444 Page 32

Page 33: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

2.2. Sử dụng câu truy vấnCú pháp :

Mệnh đề FROM và WHERE được tùy chọn. Mệnh đề FROM chỉ đặt tên cho thực thể đơn. Không hỗ trờ từ khóa JOIN.

Ta có ví dụ :

UPDATE:

1041349 - 1041397 - 1041444 Page 33

Page 34: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

DELETE :

Inheritance Mapping.(Tính kế thừa trong Hibernate)

Đặc tính của Kế thừa (Inheritance)

- Dễ sử dụng trong ngôn ngữ hướng đói tượng(object oriented language).

Java: sử dụng từ khóa “extend” hay “implement”.

- Nhưng lại không dễ sử dụng trong dữ liệu quan hệ.

Các bảng không thể “extend” từ các bảng khác được.

Vấn đề “Impedence missmatch”.

Để hiểu rõ vấn đề Impedence missmatch ta xem ví dụ sau :

 Ta có một mô hình dữ liệu có 2 table: Customers và Accounts.Như vậy chúng ta sẽ tạo mô hình object với 2 class tương ứng với 2 table này: 

1041349 - 1041397 - 1041444 Page 34

Page 35: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

 

 Nhưng mô hình object trên thiếu tính linh động và khả năng mở rộng, do đó

chúng ta nên thiết kế lại để thêm inheritance và abstraction, làm mô hình gần hơn với thực tế: 

 

Chúng ta có thể thấy rõ ràng sự không đối xứng (mismatch) giữa mô hình dữ liệu và mô hình object trong trường hợp này. Trong database, hoàn toàn chấp nhận được khi chứa toàn bộ thông tin của Person và PersonName trong một table Customers. Nhưng để tăng tốc độ thực thi, việc bảo trì và sự linh hoạt; một object lớn nên được chia thành nhiều object nhỏ.

Vậy phải giải quyết các vấn đề này như thế nào?

Trong Hibernate ta có 4 cách giải quyết :

5. Table per class hierachy.6. Table per subclass.

1041349 - 1041397 - 1041444 Page 35

Page 36: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

7. Table per concrete class.8. Đa hình tiềm ẩn.

Xét ví dụ sau đây: Ta có 3 lớp : Person, Teacher và Student. Trong đó Person là lớp cha và Teacher , Student kế thừa từ lớp cha này.Sơ đồ lớp:

Table per class hierachy.Với phương pháp nà ta sẽ ánh xạ tất cả các lớp vào duy nhất 1 bảng. tất cả các thuộc tính của các lớp sẽ hiển thị trong bảng như là một colum, trong đó sẽ có 1 cột chứa các tên lớp con mà ta gọi là “Discriminator” để phân biệt các lớp với nhau.

 Theo bảng Person trên ta thấy Discriminator lúc này là cột PERSON_TYPE chứa 2 trường dữ liệu là Sutent và Teacher. Đây là tên của hai lớp con kế thừa từ lớp cha Person.Bảng PERSON chứa tất cả các thuộc tính (attributes ) cùa các lớp Person, Teacher và Student như là các colunms của nó.Mapping cho Table class hierachy:

Person.hbm.xml

<hibernate-mapping> <class name=”Person” table=”PERSON”> <id name=”id” column=”ID”> <generator class=”increment”/> </id>

1041349 - 1041397 - 1041444 Page 36

Page 37: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<discriminator column=”PERSON_TYPE” type=”string”/> <property name= “name” column=”NAME”/> </class></hibernate-mapping>

Bảng Person có chứa column PERSON_TYPE. Column này được maped (ánh xạ) bằng cách sử dụng thẻ XML <discriminator> .Discriminator không phải là thuộc tính của bất kỳ java class nào, nó chỉ là một cột được dùng chung giữa databse và Hibernate.

Mapping file cho hai lớp Student và Teacher.

Student.hbm.xml===============

<hibernate-mapping> <subclass name=”Student” extends=Person” discriminator-value=”Student”> <property name= “branch” column=”BRANCH”/> </subclass></hibernate-mapping>

Teacher.hbm.xml===============

<hibernate-mapping> <subclass name=”Teacher” extends=Person” discriminator-value=”Teacher”> <property name= “department” column=”DEPARTMENT”/> </subclass></hibernate-mapping>

Ưu điểm :

Cách tiếp cận này thì đơn giản và hiệu quả vì tất cả các dữ liệu thì đều nằm trong cùng một bảng nên việc kết bảng lúc này thì không cần thiết.

Nhược điểm :không thể khai báo cho các subclass ràng buộc NOT NULL.

Table per concrete class

1041349 - 1041397 - 1041444 Page 37

Page 38: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Một lớp con là một bảng riêng biệt.

Bây giờ ta mapping

<union-subclass> được sử dụng cho mỗi subclass trong mapping file.

<class name="Person"> <id name="id" type="long" column="ID"> <generator class="sequence"/> </id> <property name="name" column="NAME"/> <union-subclass name="Student" table="STUDENT"> <property name="branch" column="BRANCH"/> </union-subclass> <union-subclass name="Teacher" table="TEACHER "> <property name="branch" column="BRANCH"/> </union-subclass></class>

Table per subclass:

Ta tạo ra ba bảng riêng biệt cho 3 lớp.

1041349 - 1041397 - 1041444 Page 38

Page 39: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<joined-subclass> được sử dụng cho mỗi subclass torng mapping file.

<class name="Person" table="PERSON"> <id name="id” column="ID"> <generator class="native"/> </id> <property name="name" column="NAME"/> <joined-subclass name="Teacher" table="TEACHER"> <key column="ID"/> <property name="department" column="DEPARTMENT"/> </joined-subclass> <joined-subclass name="Student" table="STUDENT"> <key column="ID"/> <property name="branch" column="BRANCH"/> </joined-subclass></class>

Trong trường hợp này ta sẽ có 3 bảng. Và khóa chính của các subclass trùng với khóa chính của lớp cha( Ở đây khóa chính của cả 3 bảng là ID).

WORKING WITH OBJECT

1.vòng đời của một object trong Hibernate.

1041349 - 1041397 - 1041444 Page 39

Page 40: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Các objects mà Hibernate quản lý phải luôn luôn ở một trong bốn trạng thái(STATE) sau đây:

5. Transient.6. Persisten.7. Removed.8. Detatched.

Các Objects muốn chuyển từ trạng thái này sang trạng thái khác sẽ được thực hiện thông qua các phương thức khác nhau.

Transient State_ Trạng thái tạm thời.

Tất cả các đối tượng khi mới khởi tạo đều ở trạng thái Transient.

-Account account = new Account();

Đối tượng account vừa được ta khởi tạo cho nên account bây giờ đang ở trạng thái tạm thời mà thôi.

Đặc điểm của các đối tượng khi đang ở trạng thái Transient State:

- Hibernate không thể nhận ra các đối tượng này .- Các đối tượng này không hề có bất kỳ liên quan đến các dữ liệu có trong

database.o Do không có giá trị cho accountID.(accountID là khóa chính.)

-khi đối tượng mới khởi tạo này không liên quan đến bất kỳ đối tượng nào khác thì nó sẽ được hủy bởi cơ chế thu gom rác(garbage collected).

PERSISTENT STATE_Trạng thái ổn định .

Với các đối tượng ở trạng thái này thì nó có các đặc điểm sau:

-Được nhận biết và chịu sự quản lý của Hibernate.- Có một database id

-là một đối tượng được tồn tại bằng việc lấy lên từ database.- hay là một đối tượng đang ở trạng thái tạm thời (Transient State)

nhưng đã được lưu.

1041349 - 1041397 - 1041444 Page 40

Page 41: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

-đây là trạng thái duy nhất mà các objecs được lưu vào database. Nói cách khác khi một object muốn được lưu vào databse điều đầu tiên là nó phải đang ở trạng thái Persisent.

-việc chỉnh sửa, cập nhật trên một đối tượng đang ở trang thái khác trạng thái này sẽ KHÔNG được lưu lại vào database .

- trong khi đó khi ta làm việc với một đối tượng đang ở trạng thái Persistent thì việc thay đổi của đối tượng này sẽ được tự động cập nhật xuống databse mà không càn gọi bất kỳ phương thức Session Persistent nào.- các đối tượng được tạo ra ổn định , lâu bền thông qua các Hibernate session:

-session.save(account);-session.update(account);-session.lock(account);-session.merge(account);

Ta xem ví dụ sau đây:

Đầu tiên ta thấy khi mới khởi tạo đối tượng account thông qua phương thức new Account() thì accoount lúc này đang ở trạng thái tạm thời mà thôi(Transient state). Hibernate không làm việc trên account đơn giản vì nó không hiểu account là gì. Vậy để Hibernate hiểu và làm việc trên account ta phải chuyển nó về trạng thái Persistent thông qua session . Lúc này việc cập nhật, thay đổi ta làm trên account sẽ được Hibernate tự động lưu xuống databse.

1041349 - 1041397 - 1041444 Page 41

Page 42: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

REMOVE STATE.

Xét đối tượng đang ở trạng thái Persistent.

Remove state là trạng thái mà mà đối tượng này đã bị delete ra khỏi database.

-session.delete(account);

Lúc này mọi thay đổi trên đối tượng này sẽ không còn được lưu xuống database nữa. Cơ chế thu gom rác của Hibernate sẽ dọn dẹp đối tượng này bởi vì Hibernate không cho phép tồn tại một đối tượng rỗng.(Đối tượng không lưu trử bất kỳ thông tin gì.)

Xét ví dụ sau đây:

Đẩu tiên khởi tạo một phiên làm việc cho Hibernate(session)

Sau đó ta lấy lên một account với id = 1 . Lúc này account được trả ra trong trạng thái Persistent.

Tiếp đó ta tiến hành delete account đi.

Lúc này mọi chỉnh sửa trên account sẽ bị Hibernate lờ đi vì account hiện tại đang ở trạng thái Remove.

Chú ý rằng trong Java thì đối tượng account lúc này sẽ vẫn còn alive, tức là ta có thể gán giá trị cho nó, làm việc với nó như một đối tượng bình thường dù đã bị delete ra khỏi

1041349 - 1041397 - 1041444 Page 42

Page 43: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

databse và đối tượng này sẽ alive cho đến khi nào lập trình viên set nó null hoặc hủy nó đi.

DETACHED STATE

Một đối tượng persistent sẽ vẫn còn được tham chiếu sau khi session của nó đã đóng lại.

Phương thức session.close() thay đổi trạng thái của đối tượng từ Persistent sang Detached.

Đặc tính:

Đối tượng lúc này vẫn đại diện cho hàng dữ liệu mà nó đang mang trong databse.

Nhưng không thuộc sự quản lý của Hibernate nữa.

Lúc này mọi sự thay đổi trên detached object sẽ không còn được lưu xuống database .

Có thể redetached ( kết nối lại) để trả về trạng thái Persistent cho đối tượng và gây ra hiện tượng là lưu lại trạng thái của chính nó xuống database.

update();

merge();

lock(); // ta retach() nhưng sẽ không lưu trạng thái .

Xét ví dụ sau :

1041349 - 1041397 - 1041444 Page 43

Page 44: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Đầu tiên khởi tạo session1.

Tạo đối tượng account thông qua session1.

Sau đó đóng session1 lại.

Lúc này account đang ở trạng thái Detached State.

Bây giờ ta muốn trả lại trạng thái Persistent cho nó thì ta re-attach lại thông qua việc mở ra một phiên làm việc mới tức là tạo ra session2.

HIBERNATE LIFECYCLE

1041349 - 1041397 - 1041444 Page 44

Page 45: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

READ ONLY ENTITIES

Trước hết ta cần hiểu qua các khái niệm sau đây:

Thế nào là entity:

Hibernate phân chia Object thành hai loại :

1. Entity Types : loại thực thể.2. Value Types : loại giá trị.

Entity object giống như phần đầu của một object. Một entity object sẽ có một định danh ID dành của riêng nó(khóa chính _Primary key) trong database. Entity object cũng có vòng đời như một object bình thường (Transient_Persistent_Remove_Detach). Và nó cũng có các mối quan hệ kết hợp với các object khác. Ví dụ ta có một object tên là Team, object này có quan hệ một hay nhiều với một object khác tên là BallPlayer( Nghĩa là một Team sẽ có một hay nhiểu

1041349 - 1041397 - 1041444 Page 45

Page 46: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

BallPlayer) . Lúc này BallPlayer object là một object thuộc loại entiy Type trong Hibernate.

theo như hình min họa trên ta thấy được rằng các Entity type có định danh duy nhất của riêng mình , và nó chính là một dòng trong bảng dữ liệu BallPlayer.Value object :Cá đặc tính của value object:-Không có định danh ID trong database như entity object.- Các value object thuộc về một entity object nào đó.Tuổi thọ của các value object phụ thuộc vào thực thể mà nó đang thuộc về. Các loại dữ liệu mà value object có thể có là : String(chuỗi);Date(ngày tháng); Integer(số nguyên);….Dirty Checking trong Hibernate:Khi một Persistent object được update thì Hibernate sẽ tự động udate những thay đổi trên đối tượng xuống database. Quá trình thực hiện xuống database của Hibernate được gọi là dirty-check.

-Khi nào thì thực thể (entity) là read-only:

- Hibernate không thực hiện dirty-check đối với thực thể đó nữa.

Trong một số trường hợp, Hibernate cũng làm việc với các entity object này như các entyti object mà không phải là read-only.

1041349 - 1041397 - 1041444 Page 46

Page 47: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Một read-only entity có thể bị delete.

Hibernat thực hiện được việc tối ưu hóa của mình thông qua các read-only entity:

- Nó tiết kiệm được thời gian do không không cần phải dirty-check các entity này.

- Nó tiết kiệm được bộ nhớ qua việc xóa các read-only entity.

1. Làm cho một persistent entity trở thành read-only:

Nên nhớ rằng chỉ khi entity đang ở trang thái persistent(trang thái ổn định) thì ta mới có thể chuyển nó thành read only được. Nếu nó đang ở trang thái Transient hay detched thì ta phải chuyển nó sang trạng thái persistent trước , sau đó ta mới có thể chuyển sang read only.Hibernate cung cấp các cách sau đây để làm cho entity chuyển sang read-only:

Có thể ánh xạ entity class là “immutalbe”( không thay đổi) ; khi một thự thểc entity nằm trong một immutable class thì nó đã được persistent rồi , lúc này Hibernate sẽ tự động làm cho nó read only.

Ta có thể thay đổi tình trrạng mặc định,default, nên khi ta các entity được load lên trong session thì Hibernate sẽ tự động làm cho nó read-only.

Cách khác ta có thể thực hiện câu HQL(Hibernate Query Language) query hoặc HQL criteria chỉ cho phép đọc nên khi các entity được load lên trong khi thực hiện câu truy vấn hay criteria như excute, scroll, hay là iterates , thì các entity này sẽ được tữ động chuyển thành read only.

Hoặc ta có thể chuyển nó sang read only bằng cách gọi thực hiện trong session.

Bây giờ chúng ta sẽ xem xét từng cách chuyển entity thành read only do Hibertnate cung cấp mà ta đã nói ở trên.

Entities of immutable classes

Sử dụng từ khóa mutable trong file mapping.

mutable = false : immutable.

1041349 - 1041397 - 1041444 Page 47

Page 48: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

<!-- Stock.hbm.xml -->...<hibernate-mapping> <class name="com.mkyong.common.Stock" table="stock" mutable="false" > <set name="stockDailyRecords" mutable="false" cascade="all" inverse="true" lazy="true" table="stock_daily_record" > <key> <column name="STOCK_ID" not-null="true" /> </key> <one-to-many class="com.mkyong.common.StockDailyRecord" /> </set> </class>... </hibernate-mapping>

Loading persistent entities as read-only

ta chuyển entity sang read only qua session:

1. Sử dụng phương thức setDefaultReadOnly

Session.setDefaultReadOnly( true );

2. Sử dụng isDefaultReadOnly

Session.isDefaultReadOnly();

 Loading read-only entities from an HQL query/criteria

Trong HQL query ta gọi hàm:

Query.setReadOnly( true );

1041349 - 1041397 - 1041444 Page 48

Page 49: Hibernate

Báo cáo đề tài tìm hiểu Hibernate-phần 1

Trong HQL criteria :

Criteria.setReadOnly( true );

1041349 - 1041397 - 1041444 Page 49