Để sử dụng JDBC connection được cung cấp bởi Hibernate, file cấu hình yêu cầu 5 thuộc tính: connection.driver_class, connection.url, connection.username, connection.password, dialect.
Thuộc tính dialect bảo cho Hibernate biết SQL dialect nào được sử dụng để thao tác. Nó được sử dụng để đảm bảo các câu Hibernate Query Language (HQL) được chuyển đổi đúng với SQL dialect dưới CSDL.
Hibernate cũng cần biết vị trí (đường dẫn tương đối so với classpath của ứng dụng) và tên của các mapping file - mô tả persistent classs.
Để sử dụng Hibernate với kết nối CSDL được cung cấp bởi JNDI DataSource, bạn cần thay đổi một vài chỗ trong file cấu hình như sau:
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
org.hibernate.dialect.MySQLDialect
Bạn chỉ sử dụng loại cấu hình này khi sử dụng Hibernate với application server: Jboss, WebSphere...Thuộc tính connection.datasource phải có cùng giá trị với tên của JNDI DataSource trong cấu hình application server.
Tạo định nghĩa ánh xạ:
Các định nghĩa ánh xạ được gọi là mapping document, được sử dụng để cung cấp cho Hibernate các thông tin để lưu trữ các đối tượng đến CSDL quan hệ. Các file ánh xạ cung cấp các đặc tính như tạo lược đồ CSDL từ tập hợp các file ánh xạ.
Các định nghĩa ánh xạ cho các đối tượng persistent có thể được lưu chung với nhau trong cùng một file. Phương pháp thích hợp hơn là định nghĩa cho mỗi đối tượng được lưu trong một file.
Quy ước đặt tên cho các file ánh xạ là sử dụng tên của persistent class với phần mở rộng hbm.xml. Ví dụ: File ánh xạ cho lớp Event có tên là Event.hbm.xml.
File ánh xạ bắt đầu bằng hibernate-mapping element. Thuộc tính package thiết lập package mặc định cho lớp. Thuộc tính set, bạn cần cung cấp tên của lớp persistent khác như: Speaker và Attendee.
Thẻ class bắt đầu định nghĩa ánh xạ cho lớp persistent xác định, thuộc tính table là tên của quan hệ (relational) được sử dụng để lưu các đối tượng.
Element mô tả khóa chính của persistent class - tự động được phát sinh. Thuộc tính name định nghĩa các thuộc tính của persistent class sẽ được sử dụng để lưu giá trị của khóa chính.
Element được sử dụng để xác định tên của lớp phát sinh khóa chính cho record mới khi lưu nó. Ở đây chúng ta sử dụng lớp native.
Sau đây là danh sách các generator phổ biến được sử dụng trong Hibernate:
- increment - phát sinh id (loại long, short hoặc int) là duy nhất chỉ khi không có tiến trình khác chèn dữ liệu vào cùng bảng.
- identity - nó hỗ trợ cột id trong DB2, MySQL, MS SQL Server, Sybase và HypersonicSQL. Id được trả về có loại long, short hoặc int.
- sequence - phát sinh sequence sử dụng một sequence trong DB2, PostgreSQL, Oracle, SAP DB, McKoi hoặc Interbase. Id được trả về có loại long, short hoặc int.
- hilo - Bộ phát sinh hilo sử dụng thuật toán hilo để phát sinh id.
- native - Nó sẽ chọn id, sequence hoặc hilo phụ thuộc vào khả năng CSDL phía dưới.
Thuộc tính unsaved-value mô tả giá trị của thuộc tính id cho các thể hiện transient của lớp đó.
Các thuộc tính:
Element property của đối tượng Event thì tương tự như element id:
Mỗi element property này tương ứng với một thuộc tính trong đối tượng Event. Thuộc tính name chứa tên thuộc tính, thuộc tính type xác định loại đối tượng của thuộc tính. Column được sử dụng để lưu giá trị của thuộc tính.
Element many-to-one:
Định nghĩa mối quan hệ với lớp Location. Mối quan hệ nhiều - một sử dụng khóa ngoại để duy trì mối quan hệ giữa hai lớp persistent.
Từ hình bạn có thể suy diễn rằng: nhiều thể hiện của Event kết hợp với một thể hiện của Location. Mặc dù hình không hiển thị nó nhưng mối quan hệ này thì không phải hai chiều nghĩa là bạn có thể định vị đến Location từ Event nhưng không thể ngược lại. Ở điểm này chúng ta sẽ biểu diễn file ánh xạ của lớp Location như sau:
Ánh xạ của lớp này thì tương tự như Event mặc dù nó không có thuộc tính nhiều và thiếu mối quan hệ với các đối tượng persistent khác.
Đối với Event, element many-to-one định nghĩa tham chiếu giữa các đối tượng persistent. Ánh xạ mối quan hệ many-to-one như sau:
Thuộc tính name cung cấp tên của thuộc tính trong đối tượng và thuộc tính column xác định column được sử dụng để lưu khóa ngoại đến bảng location. Thuộc tính class cung cấp tên của lớp persistent cần quan hệ.
Một câu hỏi phổ biến được đặt ra là: làm thế nào để tạo mối quan hệ many-to-one lazy - nghĩa là đối tượng được kết hợp với nó sẽ không được rút trích khi đối tượng cha được rút trích. Các giải quyết là sử dụng proxied objects.
Proxy:
Object proxy là cách tránh rút trích một đối tượng cho đến khi cần đến nó. Định nghĩa nó bằng 2 cách:
Thêm thuộc tính proxy vào element class:
...
Sử dụng thuộc tính lazy = "true" là cách ngắn nhất để định nghĩa lớp persistent như proxy:
...
Thuộc tính lazy là true mặc định trong Hibernate 3. Cách sử dụng thể hiện proxied Location:
Session session = factory.openSession();
Event ev = (Event) session.load(Event.class, myEventId);
Location loc = ev.getLocation();
String name = loc.getName();
session.close();
Trả về thể hiện của Location là proxy. Hibernate lấy thể hiện Location khi getName() được gọi.
Collections:
File ánh xạ định nghĩa các collection của Speakers và Attendees. Collection được định nghĩa là set - nghĩa là Hibernate quản lý các collection với ngữ cảnh là java.util.Set.
Định nghĩa này khai báo rằng lớp Event có một thuộc tính tên là speakers và nó là một Set chứa các thể hiện của lớp Speaker. Lớp Event có thuộc tính tương ứng như sau:
public class Event {
private Set speakers;
...
public void setSpeakers(Set speakers) {
This.speakers = speakers;
}
public Set getSpeakers() {
return this.speakers;
}
...
}
Element key định nghĩa khóa ngoại từ bảng collection đến bảng cha. Trong trường hợp này, bảng speakers có một column event_id tham chiếu đến column id trong bảng events. Element one-to-many định nghĩa mối quan hệ với lớp Speaker.
Ngoài Set Hibernate còn hỗ trợ Map và List.
Cascade:
Các thao tác lan truyền theo tầng trên một bảng (như delete) đến các bảng kết hợp. Giả sử, khi delete Event, bạn cũng muốn delete các thể hiện Speaker kết hợp với Event. Thay vì code trong ứng dụng sẽ thực hiện, Hibernate có thể quản lý nó thay cho bạn.
Các loại cascade: all, save-update, delete, delete-orphan.
Element cascade được thêm vào many-to-one hoặc element collection. Ví dụ cấu hình sau sẽ hướng dẫn Hibernate delete các Speaker con khi Event cha bị delete:
Duyệt các đối tượng kết hợp:
Bạn có thể rút trích các đối tượng kết hợp sử dụng outer join hoặc bằng câu lệnh SELECT. Thuộc tính fetch cho phép bạn xác định các phương thức để sử dụng:
Khi thể hiện Event được load thì đối tượng Location kết hợp cũng sẽ được load bằng outer join. Nếu muốn sử dụng câu lệnh select thì sẽ sử dụng như sau:
Xây dựng SessionFactory:
Giao tiếp SessionFactory của Hibernate cung cấp các thể hiện của lớp Session để biểu diễn các kết nối đến CSDL. Thể hiện của SessionFactory là thread-safe và chia sẽ suốt ứng dụng. Các thể hiện Session không phải là thread-safe và chỉ nên được sử dụng cho một transaction hoặc đơn vị làm vị trong ứng dụng.
Cấu hình SessionFactory:
Lớp Configuration:
Lớp này là sự mở đầu runtime của Hibernate. Nó được sử dụng để load các file ánh xạ và tạo SessionFactory cho các file ánh xạ này. Mỗi lần 2 chức năng này hoàn tất, lớp Configuration có bị vứt bỏ. Tạo một thể hiện của Configuration và Session thì đơn giản nhưng bạn có một vài tùy chọn. Có 3 cách để tạo và khởi tạo đối tượng Configuration.
Đoạn mã sau sẽ load các file property và mapping được định nghĩa trong hibernate.cfg.xml và tạo SessionFactory:
Configuration cfg = new Configuration();
SessionFactory factory = cfg.configure().buildSessionFactory();
Phương thức configure() bảo Hibernate load file hibernate.cfg.xml. Nếu như nó không tồn tại thì chỉ hibernate.properties được load từ classpath. Lớp Configuration cũng có thể load mapping document:
Configuration cfg = new Configuration();
cfg.addFile("com/manning/hq/ch03/Event.hbm.xml");
Một phương pháp khác để Hibernate load mapping document là dựa vào lớp persistent. Ví dụ, code sau sẽ khiến cho Hibernate tìm file có tên là com/manning/hq/Event.hbm.xml trong classpath và load các lớp kết hợp:
Configuration cfg = new Configuration();
cfg.addClass(com.manning.hq.ch03.Event.class);
Nếu ứng dụng có 10 hoặc 100 mapping definitions. Bạn có thể tạo file JAR (ví dụ như application.jar) chứa tất cả file class và mapping definitions. Sau đó cập nhật file hibernate.cfg.xml:
Và bạn cũng có thể làm điều này với phương thức addJar của lớp Configuration:
Configuration.addJar(new java.io.File("application.jar"));
Cả 4 phương pháp này đều được sử dụng để xác định mapping definition phụ thuộc vào các yêu cầu của project. Tuy nhiên mỗi khi bạn tạo SessionFactory từ thể hiện Configuration, thì bất kỳ file mapping nào được thêm đến thể hiện của Configuration sẽ không ảnh hưởng trong SessionFactory. Nghĩa là bạn không thể thêm một lớp persistent mới một cách tự động.
Bạn có thể sử dụng thể hiện của SessionFactory để tạo thể các thể hiện của Session:
Session session = factory.openSession();
Các thể hiện của lớp Session là giao tiếp chính của Hiberante framework. Chúng cho phép bạn persist các đối tượng, truy vấn các đối tượng persistent và làm cho các đối tượng transient trở thành persistent.
Persistent các đối tượng:
Persist đối tượng transient (tạm thời) với Hibernate thì đơn giản - lưu nó với thể hiện Session:
Event event = new Event();
// populate the event
Session session = factory.openSession();
session.save(event);
session.flush();
Gọi phương thức save(....) cho thể hiện Event sẽ gán cho nó một giá trị id được phát sinh và sau đó là persist nó. Phương thức flush() ép các đối tượng persistent được giữ trong bộ nhớ được đồng bộ xuống CSDL. Session không lập tức ghi liền xuống CSDL khi đối tượng được lưu. Thay vào đó, Session sẽ sắp xếp các lần ghi để tăng tốc độ thực thi.
Nếu bạn muốn cập nhật một đối tượng đã được persistent, phương thức update() thì có sẵn. Sự khác biệt của phương thức update() so với phương thức save() là nó không gán giá trị id cho đối tượng. Bởi vì sự khác biệt này nên giao diện Session cung cấp phương thức saveOrUpdate() để xác định thao tác đúng để thực thi trên đối tượng.
Sau đây là đoạn mã để persist thể hiện Event:
Configuration cfg = new Configuration();
SessionFactory factory = cfg.buildSessionFactory();
Event event = new Event();
// populate the Event instance
Session session = factory.openSession();
session.saveOrUpdate(event);
session.flush();
session.close();
Hai dòng đầu tạo SessionFactory sau đó load file cấu hình từ classpath. Sau khi thể hiện Event được tạo và rút trích, thể hiện Session được cung cấp bởi SessionFactory sẽ persist Event này. Session được flush và close (đóng kết nối JDBC và dọn dẹp bên trong). Đó là tất cả những gì phải làm để persist các đối tượng.
Rút trích đối tượng:
Event event = (Event) session.load(Event.class, eventId);
=> trả về thể hiện của Event với id bằng với eventId.
Query query = session.createQuery("from Event");
List events = query.list();
=> trả về toàn bộ các đối tượng từ CSDL.
Sử dụng PreparedStatement cho câu truy vấn:
Query query = session.createQuery("from Event where name = ?",
"Opening Presentation");
query.setParameter(0, "Opening Presentation", Hibernate.STRING);
List events = query.list();
(Con tiếp)
DangTrung.