Đăng ký Đăng nhập
Trang chủ Công nghệ thông tin Quản trị mạng Báo cáo tìm hiểu spring mvc...

Tài liệu Báo cáo tìm hiểu spring mvc

.DOCX
31
785
64

Mô tả:

Báo cáo tìm hiểu spring mvc
1 Spring MVC Mục lục 1 Hibernate.................................................................................................................................2 1.1 ORM (Objet – relation Mapping).............................................................................................2 1.2 Kiến trúc Hibernate...................................................................................................................3 1.2.1 Interface..............................................................................................................................3 1.2.2 Một số interface chính.......................................................................................................4 1.2.3 Các interface callback........................................................................................................6 1.2.4 Type.....................................................................................................................................6 1.2.5 Các interface mở rộng.......................................................................................................7 1.3 2 1.3.1 Định nghĩa..........................................................................................................................7 1.3.2 Các cách thực hiện việc truy vấn trong Hibernate..........................................................7 1.3.3 Cách thực thi câu truy vấn................................................................................................8 1.3.4 Các thành phần trong câu truy vấn..................................................................................8 Spring MVC..........................................................................................................................13 2.1 Mô hình MVC trong ứng dụng web.......................................................................................13 2.2 Giới thiệu về Spring framework.............................................................................................14 2.2.1 IoC(Inversion of Control)................................................................................................15 2.2.2 DI(Dependency Injection)...............................................................................................15 2.3 Giới thiệu về Spring MVC......................................................................................................16 2.4 Một số thành phần quan trọng trong Spring MVC...............................................................17 2.4.1 DispatcherServlet.............................................................................................................17 2.4.2 Controllers........................................................................................................................21 2.4.3 Handler mappings................................................................................................................21 2.4.4 Một số thành phần khác............................................................................................................23 2.5 3 Truy vấn trong Hibernate - HQL (Hibernate Query Language)............................................7 Hoạt động của Spring MVC....................................................................................................23 JSTL (JSP Standard Tag Library)......................................................................................24 3.1 JSTL là gì:................................................................................................................................24 3.2 Các thư viê ên thẻ của JSTL:.....................................................................................................24 2 3.2.1 Core Action: gồm các chức năng sau..............................................................................25 3.2.2 Formatting Action:...........................................................................................................25 3.3 3.3.1 Qui ước đă êt tên.................................................................................................................26 3.3.2 Scoped Variables vs. Scripting Variables........................................................................26 3.3.3 Các thuô êc tính đô êng.........................................................................................................26 3.3.4 Xử lý lỗi.............................................................................................................................26 3.4 3.5 Nguyên tắc thiết kế:.................................................................................................................26 Thẻ General-Purpose and Conditional..................................................................................26 Thẻ Conditional................................................................................................................28 3 1 Hibernate Trong nhiều năm, persistence (việc lưu trữ một đối tượng lên ổ đĩa hay một thiết bị lưu trữ bền vững khác) là một vấn đề gây nhiều tranh cãi trong cộng đồng Java: Liệu “persistence” là vấn đề đã được giải quyết bởi công nghệ quan hệ và các mở rộng (ví dụ như các stored procedure) hay “persistence” là một vấn đề lớn cần phải được giải quyết bởi các mô hình thành phần Java đặc biệt như là các EJB entity bean; Ta nên code tay ngay cả các thao tác cơ bản nhất như create, read, update, delete trong SQL hay JDBC, hay các công việc này nên được tự động hóa; Làm thế nào để hệ thống đạt được tính khả chuyển đổi nếu mỗi hệ thống quản trị cơ sở dữ liệu (DBMS) lại có một hình thái ngôn ngữ của riêng nó (có các token, syntax, semantic riêng); Có nên từ bỏ SQL hoàn toàn và chuyển sang một công nghệ cơ sở dữ liệu mới, ví dụ như các hệ thống cơ sở dữ liệu đối tượng. Cuộc tranh luận vẫn còn tiếp tục nhưng hiện nay đã có một giải pháp nhận được sự chấp thuận ngày càng tăng. Giải pháp này có tên gọi là ánh xạ đối tượng/quan hệ (ORM – object/relational mapping). Hibernate là một sự hiện thực ORM mã nguồn mở. Hibernate là một dự án với mục tiêu trở thành một giải pháp hoàn chỉnh cho vấn đềquản lý dữ liệu persistent trong Java. Nó làm trung gian cho các tương tác của ứng dụng với một cơ sở quan hệ, giải phóng nhà phát triển để họ có thể tập trung vào các vấn đề nghiệp vụ. Hibernate kkông phải là một giải pháp bắt buộc (non-intrusive solution). Nghĩa là ta không cần phải theo các luật cụ thể cho Hibernate và các design pattern khi viết các logic nghiệp vụ và các class persistent. Do đó Hibernate tích hợp tốt với hầu hết các ứng dụng mới và đang tồn tại mà không yêu cầu những thay đổi đối với phần còn lại của chương trình. 1.1 ORM (Objet – relation Mapping) Một ánh xạ đối tượng/quan hệ (object/relational mapping) là một sự thường trú tự động (persistence) của các đối tượng thuộc một ứng dụng Java trong các table thuộc một cơ sở dữ liệu quan hệ bằng cách sử dụng các metadata mô tả sự ánh xạ giữa các đối tượng và cơ sở dữ liệu. Về bản chất, ORM, làm việc thông qua sự chuyển đổi dữ liệu từ một dạng thể hiện này sang một dạng khác. Một giải pháp ORM cấu tạo bởi bốn phần sau:  Một API để thực hiện các giao thức CRUD cơ bản trên các đối tượng của các class persistent.  Một ngôn ngữ hoặc API để thực hiện các câu truy vấn trên các class và các thuộc tính của class.  Một tiện ích để xác định các ánh xạ metadata.  Một kỹ thuật cho việc hiện thực ORM để tương tác với các đối tượng giao dịch để thực hiện dirty checking, lazy association fetching và các chức năng tối ưu khác. 1.2 Kiến trúc Hibernate 4 1.2.1 Interface Các interface lập trình (programming interface) là điều đầu tiên cần biết về Hibernate để sử dụng nó trong tầng persistencecủa ứng dụng của bạn. Một mục tiêu chính của thiết kế API là giữ cho các interface giữa các thành phần phần mềm càng gần nhau càng tốt. Tuy nhiên trong thực tế, các ORM API không hề ít. Tuy vậy, ta cũng không cần phải hiểu tất cả interface Hibernate một lúc. Hình 1.1 mô tả các vai trò của của các interface Hibernate quan trọng nhất trong tầng nghiệp vụ (business layer) và tầng persistence (persistence layer). Tầng nghiệp vụ nằm trên tầng persistence, bởi vì tầng nghiệp vụ hoạt động như một client của tầng persistence trong một ứng dụng phân lớp truyền thống. Lưu ý rằng, một số ứng dụng đơn giản có thể không tách biệt logic nghiệp vụ khỏi logic persistence. Điều đó chỉ làm đơn giản lược đồ hơn. Hình 1.1. Tổng quan về Hibernate API trong kiến trúc phân tầng Các interface Hibernate được thể hiện trên hình trên có thể được phân thành các loại chính sau:  Các interface được các ứng dụng gọi để thực hiện các thao tác cơ bản CRUD và các lệnh truy vấn. Chúng bao gồm Session, Transaction và Query.  Các interface được code cơ sở ứng dụng gọi để cấu hình Hibernate, trong đó quan trọng nhất là interface Configuration. 5  Các interface Callback – là các interface cho phép ứng dụng phản hồi lại các sự kiện (event) xảy ra bên trong Hibernate, gồm các interface như Interceptor, Lifecycle và Validatable.  Các interface giúp mở rộng các chức năng ánh xạ của Hibernate, gồm các interface như UserType, CompositeUserType, và IdentifierGenerator. Các interface này được hiện thực bằng code cơ sở ứng dụng. Hibernate sử dụng các API Java có sẵn, bao gồm JDBC, JTA, JNDI. JDBC cung cấp một trừu tượng hóa ban đầu các chức năng thông dụng của cơ sở dữ liệu quan hệ, cho phép hầu hết các cơ sở dữ liệu với một JDBC driver được Hibernate hỗ trợ. JNDI và JTA cho phép Hibernate tích hợp với J2EE server ứng dụng. 1.2.2 Một số interface chính Sử dụng các interface này, bạn có thể lưu trữ và rút trích các đối tượng persistent và điều khiển các transaction. - Session interface: o Một thực thể Session ít tốn tài nguyên (có tính lightweight), dễ dàng tạo và hủy. Đặc điểm này khá quan trọng vì trong một ứng dụng cần tạo và xóa các session mọi lúc, có thể là trên mỗi request. Các Hibernate session không có tính an toàn về thread (not threadsafe) nên được thiết kế để chỉ được một thread sử dụng một thời điểm. o Định nghĩa của Hibernate về một session là một cái giữa connection và transaction. Có thể hình dung về session như một bộ đệm hoặc một tập hợp các đối tượng đã được nạp vào có liên quan đến một đơn vị công việc. Hibernate có thể dò tìm ra những thay đổi các đối tượng trong đơn vị công việc này. Nó cũng là interface cho các hàm liên quan đến persistent, ví dụ như là việc lưu và rút trích đối tượng. - SessionFactory interface o Ứng dụng tạo được một thực thể Session từ một SessionFactory. SessionFactory không có tính lighweight. Nó được dùng chung cho nhiều thread ứng dụng. Điển hình là có một SessionFactory cho toàn ứng dụng, được tạo trong phần khởi tạo ứng dụng. Tuy nhiên, nếu ứng dụng cần truy xuất nhiều database bằng cách sử dụng Hibernater thì cần một SessionFactory cho mỗi database. o SessionFactory lưu lại các câu lệnh SQL đã tạo và các siêu dữ liệu (metadata) ánh xạ khác mà Hibernate sử dụng ở thời điểm chạy. Nó cũng lưu các dữ liệu đã từng được đọc (được cache lại) trong một đơn vị công việc và có thể được sử dụng trong một đơn vị công việc trong tương lai (chỉ nếu các ánh xạ class và collection xác định rằng cache cấp hai này là cần thiết). 6 - Configuration interface Đối tượng Configuration được sử dụng để định cấu hình và boostrap Hibernate. Ứng dụng sử dụng một thực thể Configuration để xác định vị trí của các tài liệu ánh xạ (mapping document) và các thuộc tính xác định Hibernate và sau đó tạo ra SessionFactory. - Transaction interface o Interface Transaction là một API tùy chọn. Nghĩa là các ứng dụng Hibernate có thể không sử dụng interface này, thay vào đó nó sẽ quản lý các transaction bằng code cơ sở của riêng nó. Một Transaction interface tách biệt (trừu tượng hóa) code ứng dụng khỏi sự hiện thực transaction bên dưới (có thể là transaction JDBC, UserTransaction JTA hoặc transaction CORBA) cho phép ứng dụng điều khiển các biên transaction (transaction boundary – cho phép xác định khi nào một transaction bắt đầu và kết thúc) thông qua một API nhất quán. o Điều này giúp cho các ứng dụng Hibernate có tính khả chuyển trên các môi trường thực thi và các container khác nhau. - Query và Criteria interface o Interface Query cho phép thực hiện các truy vấn đến các cơ sở dữ liệu và điều khiển việc các truy vấn này được thực thi như thế nào. Các truy vấn được viết bằng HQL (Hibernate Query Language) hoặc bằng ngôn ngữ SQL nguyên thuỷ. Một thực thể Query được dùng để bind các thông số truy vấn, giới hạn của số kết quả trả về bởi truy vấn và nhiệm vụ cuối cùng là thực thi truy vấn. o Interface Criteria cũng tương tự như vậy, nó cho phép tạo và thực thi các truy vấn chuẩn hướng đối tượng. o Một thực thể Query có tính lightweight và không thể sử dụng ngoài Session đã tạo ra nó. 1.2.3 Các interface callback Interface Callback cho phép các ứng dụng nhận một thông báo khi có một sự kiện xảy ra đối với một đối tượng – ví dụ như khi đối tượng được nạp vào, được lưu hoặc bị xoá. Các ứng dụng Hibernate không cần hiện thực những callback này nhưng chúng sẽ có ích cho việc hiện thực các loại chức năng tổng quát, như là tạo ra các bản ghi kiểm toán (audit record). Gồm các interface như: - Lifecycle và Validatable: cho phép một đối tượng persistent phản hồi các sự kiện liên quan đến vòng đời (lifecycle) persistent của riêng nó. 7 - Interceptor cho phép ứng dụng xử lý các callback mà không buộc các class persistent hiện thực các API đặc trưng của Hibernate (Hibernate-specific API). Cáchiện thực interface Interceptor được truyền đến các thực thể persistent như các thông số. 1.2.4 Type Một thành phần cơ bản và rất mạnh của kiến trúc này định nghĩa của Hibernate về Type. Một đối tượng Type của Hibernate ánh xạ một kiểu của Java đến một kiểu cột của cơ sở dữ liệu (database column type). Kiểu này có thể kéo dài qua nhiều cột. Tất cả các thuộc tính persistent của class persistent, bao gồm các quan hệ (association), có môt kiểu Hibernate tương ứng. Điều này làm cho Hibernate trở nên đặc biệt linh hoạt và dễ mở rộng. Có rất nhiều kiểu Hibernate đã được xây dựng sẵn, bao gồm tất cả các kiểu gốc củaJava (Java primitive) và nhiều class JDK, bao gồm các kiểu cho java.util.Currency, java.util.Calendar, byte[] và java.io.Serializable. Hơn thế nữa, Hibernate còn hỗ trợ cho kiểu tuỳ chỉnh do người dùng tự định nghĩa (user-defined custom type). Các interface UserType và CompositeType cho phép thêm vào kiểu riêng của người sử dụng. Đặc tính này giúp điều khiển các class ứng dụng được sử dụng rộng rãi như là Address, Name, MonetaryAmount một cách thuận tiện.Các kiểu tuỳ chỉnh được xem như là một đặc tính chính của Hibernate và được khuyến khích dùng. 1.2.5 Các interface mở rộng Nhiều chức năng mà Hibernate cung cấp có khả năng định cấu hình. Điều này cho phép ta chọn giữa nhiều chiến lược được xây dựng sẵn. Khi các chiến lược này không đủ hiệu quả, Hibernate cho phép thêm vào các hiện thực của riêng người dùng bằng cách hiện thực một interface. Các điểm mở rộng gồm có:  Tạo khoá chính: interface IdentifierGenerator.  Hỗ trợ hình thái ngôn ngữ SQL: class trừu tượng Dialect.  Các chiến lược lưu trữ đệm – cache: interface Cache và CacheProvider.  Quản lý kết nối JDBC: interface ConnectionProvider.  Quản lý transaction: interface TransactionFactory, Transaction và TransactionManagerLookup.  Các chiến lược ORM: phân cấp interface ClassPersister.  Các chiến lược truy cập thuộc tính: interface PropertyAccessor.  Tạo proxy: interface ProxyFactor. 1.3 Truy vấn trong Hibernate - HQL (Hibernate Query Language) 1.3.1 Định nghĩa 8 Hibernate cũng có một ngôn ngữ truy vấn cho riêng nó, tên là Hibernate Query Language, gọi tắt là HQL. Về mặt cấu trúc HQL cũng tương tự như SQL với các mệnh đề SELECT, FROM và WHERE. HQL cũng hỗ trợ subselect nếu cơ sở dữ liệu bên dưới cũng hỗ trợ. Nhưng thật sự HQL là ngôn ngữ truy vấn hướng đối tượng với các khái niệm về thừa kế (inheritence), tính đa hình (polymorphism) và quan hệ association). 1.3.2 Các cách thực hiện việc truy vấn trong Hibernate Thực ra trong Hibernate ta có thể dùng đến 3 cách để biểu diễn câu truy vấn. - Cách thứ nhất là sử dụng HQL: Ví dụ: session.createQuery(“from Category c where c.name like ‘Laptop%’”); - Cách thứ hai là sử dụng hàm API Criteria cho truy vấn, gồm truy vấn theo chuẩn (query by criteria, QBC) và truy vấn theo ví dụ (query by example, QBE). Ví dụ: session.createCriteria((Category.class).add(Expression.like("name","Laptop %")); - Cách thứ ba là sử dụng câu SQL trực tiếp với sự ánh xạ tự động tập kết quả thành các đối tượng. Ví dụ: session.createSQLQuery("select {c.*} from CATEGORY {c} where NAME like 'Laptop%'","c",Category.class); Trong tài liệu này chúng ta chỉ đề cập đến cách truy vấn đầu tiên. Nếu cần tham khảo thêm về hai cách còn lại, các bạn có thể tham khảo thêm tài liệu Hibernate in Action, chương 7 “Retrieving objects efficiently”. 1.3.3 Cách thực thi câu truy vấn - Interface cho việc truy vấn (query interface) Để tạo một thực thể Query mới ta có thể gọi hàm createQuery(). Ví dụ: Query hqlQuery = session.createQuery("from User"); - Phân trang kết quả Phân trang là một kỹ thuật thường được sử dụng. Người sử dụng có thể nhìn thấy kết quả tìm kiếm (ví dụ, tìm các Nhânviên trong một công ty) trong một trang. Trang này chỉ hiển thị giới hạn một tập con của kết quả (ví dụ, 10 nhân viên) vào một thời điểm, và người sử dụng có thể chuyển sang trang kết quả kế tiếp hoặc quay lại trang kết quả trước đó. Interface Query hỗ trợ việc phân trang của kết quả truy vấn: Query query = session.createQuery(“from User u order by u.name asc”); query.setFirstResult(0); query.setMaxResult(10); 9 Hàm setMaxResult(10) giới hạn tập kết quả truy vấn đến 10 đối tượng đầu tiên được chọn ra (select) trong cơ sở dữ liệu. 1.3.4 Các thành phần trong câu truy vấn - Mệnh đề FROM Mệnh đề FROM cho phép xác định các đối tượng sẽ được truy vấn. Nó cũng cho phép tạo ra các bí danh cho tên đối tượng. Giả sử ta muốn truy vấn tất cả các thực thể Event có tên là “Festival”, câu truy vấn sẽ như sau: FROM Event e WHERE e.name = “Festival” Câu truy vấn này có một cái tên bí danh cho thực thể Event là e. Tên bí danh này có thể được sử dụng giống như trong câu truy vấn SQL ngoại trừ việc ở đây ta sử dụng nó để định danh các đối tượng thay vì định danh các bảng như trong SQL. Một điểm cần lưu ý trong câu truy vấn HQL trên là nó đang truy vấn trên một thuộc tính của đối tượng Event: thuộc tính name. Như vậy là khi truy vấn ta không dùng tên cột trong bảng mà dùng tên thuộc tính. Do HQL sử dụng theo các khái niệm hướng đối tượng, vì vậy không thể viết tắt e.name thành name được. Tên thuộc tính phải luôn được đi kèm với tên đối tượng. Rõ ràng là khi sử dụng HQL, ta không quan tâm đến table và column dữ liệu quan hệ bên dưới mà tập trung vào các thuộc tính của các đối tượng. Khi truy vấn chỉ liên quan đến một đối tượng, thì chỉ cần một đối tượng List chứa các thực thể của đối tượng truy vấn. Nếu cần truy vấn nhiều đối tượng có liên quan đến nhau (các đối tượng có quan hệ với nhau), mệnh đề FROM sẽ chứa nhiều đối tượng: Ví dụ: FROM Event e, Attendee a WHERE … Và danh sách kết quả sẽ chứa một phép tích Cartesian các đối tượng được truy vấn (phép tích Cartesian là kết quả của việc kết hợp mỗi dòng của môt bảng với mỗi dòng của một bảng khác) mà rất có thể nó không phải là sản phẩm ta mong muốn. Để truy vấn trên nhiều đối tượng có liên quan đến nhau, ta cần kết hợp (join) chúng trong mệnh đề FROM. - Kết hợp (Join) Trong SQL cũng có phép JOIN trả về dữ liệu từ nhiều bảng với một câu truy vấn duy nhất. Tuy nhiên phép JOIN trong HQL chỉ kết hợp các thuộc tính của đối tượng và các quan hệ, trong khi phép JOIN trong SQL kết hợp các bảng. Nếu cần truy vấn các thực thể của đối tượng Event mà một người tham dự (Attendee) xác định sắp tham gia, ta phải kết hợp thuộc tính attendee với đối tượng Event trong câu truy vấn: FROM Event e join e.attendee a WHERE a.id = 321 Trong HQL, ta có thể kết hợp tất cả các quan hệ (nhiều-một và một-một), cũng như các tập hợp với đối tượng cơ sở của truy vấn. Đối tượng cơ sở trong một truy vấn là đối tượng hiện diện trong mệnh đề FROM. Trong ví dụ trên, đối tượng cơ sở là Event. Trong ví dụ trên, ta có thể đặt một bí danh cho quan hệ được kết hợp và truy vấn trên các thuộc 10 tính trong đối tượng được kết hợp. Quy tắc đặt tên cho bí danh của HQL là sử dụng chữ viết thường. o Các loại kết hợp HQL có nhiều kiểu kết hợp khác nhau, các kiểu kết hợp này đều có trong SQL, chỉ có một kiểu kết hợp là ngoại lệ. Bảng sau tóm tắt các kiểu kết hợp Loại kết hợp Luật inner join Các đối tượng không phù hợp với nhau ở một trong hai đầu kết hợp sẽ bị loại bỏ. left (outer) join Trả về tất cả đối tượng ở đầu trái của kết hợp. Nếu đối tượng ở đầu trái của kết hợp không có đối tượng nào trùng khớp (match) ở đầu phải của kết hợp thì nó vẫn được trả về. right (outer) join Trả về tất cả đối tượng ở đầu phải của kết hợp. Nếu đối tượng ở đầu phải của kết hợp không có đối tượng nào trùng khớp (match) ở đầu trái của kết hợp thì nó vẫn được trả về. full join Trả về tất cả đối tượng ở cả hai đầu kết hợp, bất kể có hay không đối tượng trùng khớp ở đầu đối diện của kết hợp. inner join fetch Được sử dụng để truy xuất một đối tượng kết hợp hoặc một tập hợp các đối tượng bất kể có hay không outer-join hoặc lazy property trên quan hệ. Loại kết hợp này không có trong SQL. Loại kết hợp mặc định được sử dụng là inner join. Muốn sử dụng loại khác ta phải xác định chính xác loại kết hợp trong mệnh đề kết hợp (left, right, full). Tất cả các loại kết hợp đều có loại tương ứng trong SQL, ngoại trừ inner join fetch. Kết hợp một lazy collection với inner join fetch sẽ làm cho collection này được trả về khi populated. Ví dụ: FROM Event e INNER JOIN FETCH e.speakers Câu truy vấn này sẽ trả về tất cả các thực thể Event với các tập hợp của Speakers (nghĩa là một thực thể Event sẽ có một tập các Speaker tương ứng với Event đó). Xét sự kết hợp một đối tượng có quan hệ một-nhiều với một đối tượng cơ sở: FROM Event e JOIN e.location l WHERE l.name = :name Kết hợp thực thể Location với đối tượng Event cho phép truy vấn trên các thuộc tính của Location, và đạt được kết quả truy vấn hiệu quả hơn. Giải thích: Nếu không dùng phép kết hợp join này ta có thể có câu truy vấn sau: FROM Event e WHERE e.location.name = :name AND e.location.address.state = :state Vì ta phải duyệt qua các đối tượng hai lần, một lần cho tên của Location và một lần cho trạng thái (state) của Location, do đó trình biên dịch truy vấn sẽ kết hợp thực thể Location với Event hai lần. Kết hợp Location với Event trong mệnh đề FROM sẽ chỉ phải thực hiện phép kết một lần và truy vấn cũng thực hiện hiệu quả hơn. Các đối tượng trong phép kết cũng có thể được trả về trong mệnh đề SELECT của câu lệnh HQL. - Mệnh đề SELECT Mệnh đề SELECT cho phép xác định một danh sách các giá trị trả về từ câu truy vấn. Giá trị trả về có thể là toàn bộ đối tượng, các thuộc tính xác định của đối tượng và 11 giá trị dẫn xuất từ một truy vấn. Giá trị dẫn xuất bao gồm kết quả từ các hàm chức năng, như là hàm min(), max() và hàm count(). Một đặc điểm của HQL là khả năng trả về các đối tượng mới từ các giá trị được chọn. o Phép chiếu: Phép chiếu là việc chọn các cột xác định của dữ liệu trả về từ một truy vấn. Giả sử thay vì trả về toàn bộ đối tượng Event trong câu truy vấn, ta chỉ muốn lấy tên của Event. Việc truy xuất toàn bộ đối tượng chỉ để lấy thuộc tính tên thì rất không hiệu quả. Thay vào đó, câu truy vấn chỉ cần truy xuất đến dữ liệu mong muốn: SELECT e.name FROM Event e Câu truy vấn này trả về một danh sách các thực thể kiểu chuỗi chứa các tên của Event. Nếu muốn truy xuất hai thuộc tính, ví dụ như ngày bắt đầu và tên của Event: SELECT e.name, e.startDate FROM Event e Mỗi phần tử trong danh sách trả về là một array kiểu Object (Object[]) chứa các giá trị xác định. Chiều dài của array Object[] bằng với số cột được yêu cầu truy xuất. Sau đây là một ví dụ về cách thức truy vấn và xử lý truy vấn trên nhiều thuộc tính. Ví dụ: Session session = factory.openSession(); String query = " select e.name, e.startDate from Event e "; Query query = session.createQuery("query"); List results = query.list(); for (Iterator I = results.iterator(); i.hasNext();) { Object[] row = (Object[]) i.next(); String name = (String) row[0]; Date startDate = (Date) row[1]; // … } Lưu ý rằng các giá trị trong array Object[] có thứ tự giống với thứ tự các thuộc tính trong câu truy vấn. Array chứa các thực thể thuộc kiểu Object, không có giá trị thuộc kiểu cơ bản (gồm các kiểu như int, long, boolean…) có thể được trả về từ một truy vấn dạng này. Giới hạn này cũng vẫn tồn tại khi truy vấn một giá trị đơn, bởi vì một List không thể chứa các giá trị kiểu cơ bản. Một cách thông dụng để xử lý vấn đề này là dùng các đối tượng giản lược (summary object) chứa một tập con dữ liệu của đối tượng. Trong trường hợp ví dụ trên, một đối tượng giản lược sẽ chứa thuộc tính name và startdate của Event. Khi duyệt trên danh sách kết quả, ta sẽ cần một danh sách cho các đối tượng giản lược. Có một cách tốt hơn để giải quyết vấn đề trên. o Trả về các đối tượng mới Mệnh đề SELECT có thể được sử dụng để tạo ra các đối tượng mới, giữ các giá trị trong câu truy vấn. Xét ví dụ sau: select new EventSummary(e.name, e,startDate) from Event e 12 Danh sách kết quả sẽ được trả về theo các thực thể của đối tượng EventSummary. Dĩ nhiên class EventSummary phải có một constructor tương ứng với constructor được sử dụng trong câu lệnh HQL: EventSummary(String, Date). Phần trước đã trình bày về những thành phần chính của câu truy vấn HQL. Phần sau sẽ trình bày về các hàm tập hợp (aggregate functions) có sẵn trong HQL và cách chúng được sử dụng trong mệnh đề SELECT và WHERE. o Sử dụng các hàm Các hàm là các lệnh đặc biệt, trả về một giá trị được tính toán. Trong SQL có hai kiểu hàm: hàm kết hợp và hàm vô hướng (scalar). Các hàm vô hướng thường xử lý trên một giá trị đơn và trả về một giá trị đơn. Cũng có các hàm vô hướng không cần đối số, như hàm now() hoặc CURRENT_TIMESTAMP, cả hai đều trả về thời gian của hệ thống (timestamp). Các hàm tập hợp xử lý trên một tập các giá trị trả về giá trị tổng kết (summary value). Hibernate hỗ trợ năm hàm tập hợp trong SQL thông dụng nhất, gồm: count (đếm phần tử trong tập hợp thỏa ràng buộc), avg (tính trị trung bình), min (tính trị nhỏ nhất), max (tính trị lớn nhất) và sum (tính tổng các giá trị). Các hàm này có chức năng tương tự như các hàm tương ứng trong SQL. Xét ví dụ sau: SELECT COUNT(e) FROM Event e Ví dụ này trả về số đối tượng Event có trong cơ sở dữ liệu. Để đếm số đối tượng Event và không đếm trùng các đối tượng giống nhau, sử dụng từ khóa distinct: SELECT COUNT(DISTINCT e) FROM Event e Tất cả các hàm tập hợp đều trả về một đối tượng Integer. Để truy xuất kết quả, cách đơn giản nhất là lấy giá trị đầu tiên trong danh sách kết quả: Integer count = (Integer) session.find (“select count(distinct e) from Event e”).get(0); Xét một ví dụ khác: lấy tập hợp những người tham gia (Attendee) cho một sự kiện cho trước. Hiện nay để lấy được thông tin này thì code sẽ như sau: String query = “from Event e inner join fetch e.attendees where e.name = :name”; Query q = session.createQuery(query); q.setParameter(“name”, ”Meeting”); Event event = (Event) q.list().get(0); Set attendees = event.getAttendees(); session.close(); Có một cách khác ngắn hơn nhiều để đạt được tập hợp con. Hibernate cung cấp hàm elements(…) để trả về các thành phần của một tập hợp: SELECT elements(e.attendees) FROM Event e WHERE e.name = :name Câu truy vấn trả về một đối tượng List chứa các thực thể Attendee ứng với sự kiện Event. Nếu sử dụng phép kết hợp trong mệnh để FROM, ta có thể sử dụng alias trong phép kết hợp làm đối số của hàm. Câu truy vấn sau cũng tương đương với câu trên: SELECT elements(a) FROM Event e JOIN e.attendees a WHERE e.name =: name 13 Các hàm cũng có thể được sử dụng trong mệnh đề WHERE. o Các thuộc tính có sẵn của HQL Các thuộc tính có sẵn của HQL dành cho các đối tượng trong câu truy vấn. HQL hỗ trợ hai thuộc tính đối tượng: id và class. Thuộc tính id cho phép truy xuất đến giá trị khóa chính của một đối tượng trong cơ sở dữ liệu. Bất kể ta đặt tên cho thuộc tính id trong đối tượng và trong định nghĩa ánh xạ là gì thì sử dụng id trong câu truy vấn HQL vẫn sẽ trả về giá trị khóa chính. Ví dụ, nếu có một class với thuộc tính id được đặt tên là objectId, ta vẫn có thể sử dụng thuộc tính id trong câu truy vấn HQL: FROM MyObject m WHERE m.id > 50 Ta vẫn có thể sử dụng thuộc tính objectId nếu muốn. Có thể xem thuộc tính Id của HQL như một cách viết gọn cho giá trị khóa chính. Thuộc tính class cung cấp chức năng tương tự. Thuộc tính class giúp truy xuất đến tên class Java của các đối tượng trong cơ sở dữ liệu. Điều này đặc biệt có ích khi ta ánh xạ một phân cấp class trong cơ sở dữ liệu và chỉ muốn trả về các class thuộc một kiểu xácđịnh. Xét ví dụ sau để thấy thuộc tính class được sử dụng như thế nào. Ví dụ class Attendee có quan hệ với class Payment. Class Payment xác định cách Attendee sẽ trả tiền cho các Event. Payment có hai class con (subclass): CreditCardPayment và CashPayment. Câu truy vấn sau sẽ truy xuất được tất cả Attendee trả bằng tiền mặt: FROM Attendee a JOIN a.payment p WHERE p.class = de.laliluna.CashPayment Cũng giống như thuộc tính id, ta cũng có thể trả về thuộc tính class trong lệnh SELECT SELECT p.id, p.class FROM Payment p; Câu truy vấn trả về tất cả các id và class cho đối tượng Payment trong một đối tượng List gồm các phần tử là array Object[]. Tuy nhiên, thuộc tính class không được trả về như là một thực thể của java.lang.Class. Thay vào đó, thuộc tính class là môt thực thể java.lang.String, có giá trị là giá trị được xác định trong thuộc tính discriminor-value (tạm dịch là giá trị phân biệt) trong định nghĩa ánh xạ. Thuộc tính class chỉ có trong phân cấp đối tượng. Nói cách khác là thuộc tính class chỉ có trong các đối tượng được ánh xạ với một discriminator-value. Nếu truy xuất thuộc tính class của một đối tượng không có discriminator-value sẽ nhận ngoại lệ QueryException báo rằng bộ phân tích truy vấn (query parser) không thể phân tích được thuộc tính class này. Các thuộc tính id và class có thể được sử dụng trong mệnh đề SELECT và WHERE. o Sử dụng biểu thức Các biểu thức được sử dụng để truy vấn các đối tượng có thuộc tính thỏa mãn các tiêu chuẩn xác định. Được sử dụng trong mệnh đề WHERE của truy vấn, các biểu thức hỗ trợ hầu hết các toán tử thông dụng trong SQL. Tóm lại: Hibernate là một công nghệ mới giải phóng cho người phát triển code khỏi cơ sở dữ liệu quan hệ thực sự bên dưới. Người phát triển chỉ cần biết các class ánh xạ từ cơ sở dữ liệu bên dưới mà không phải làm việc với các bảng (table). 14 2 Spring MVC 2.1 Mô hình MVC trong ứng dụng web MCV (Model View Controller) là tên một phương pháp chia nhỏ một ứng dụng thành ba thành phần để cài đặt, mỗi thành phần đóng một vai trò khác nhau và ảnh hưởng lẫn nhau, đó là models, views, và controllers. Models (Tầng dữ liệu): là một đối tượng hoặc một tập hợp các đối tượng biểu diễn cho phần dữ liệu của chương trình, ví dụ như các dữ liệu được lưu trong database, dữ liệu từ một hệ thống các ứng dụng khác như legacy system, file system, mail system …  Views (Tầng giao diện) : là phần giao diện với người dùng, bao gồm việc hiện dữ liệu ra màn hình, cung cấp các menu, nút bấm, hộp đối thoại, chọn lựa …, để người dùng có thể thêm, xóa. sửa, tìm kiếm và làm các thao tác khác đối với dữ liệu trong hệ thống.. Thông thường, các thông tin cần hiển thị được lấy từ thành phần Models.  Controllers (Tầng điều khiển): chịu trách nhiệm xử lý các tác động về mặt giao diện, các thao tác đối với models, và cuối cùng là chọn một view thích hợp để hiển thị ra màn hình. Trong kiến trúc MVC, view chỉ có tác dụng hiển thị giao diện mà thôi, còn điều khiển dòng nhập xuất của người dùng vẫn do Controllers đảm trách.  15 2.2 Giới thiệu về Spring framework Spring Framework, hay ngắn hơn là Spring, là một cấu trúc dùng để xây dựng chương trình ứng dụng mã nguồn mở dành cho ngôn ngữ lập trình Java. Spring Framework cung cấp các giải pháp cho nhiều thách thức kỹ thuật mà các nhà phát triển phần mềm Java và các tổ chức muốn tạo ứng dụng dựa trên nền tảng Java phải đối mặt với Java platform. Bởi vì số lượng lớn chức năng của Spring Framework, việc phân loại những bộ phận cơ bản kiến tạo nên bộ khung là một việc rất khó. Spring Framework không chỉ được liên kết riêng biệt với Java Enterprise platform mặc dù sự tích hợp sâu của Spring trong Java EE là một yếu tố quan trọng cho sự phổ dụng, nổi tiếng của nó. Có lẽ Spring Framework nổi tiếng nhất với sự cung cấp một cách hiệu quả các tính năng cần thiết để tạo ra các ứng dụng thương mại phức tạp, vượt lên khỏi các mô hình lập trình từng chiếm vị trí ưu thế trong lịch sử ngành công nghiệp phần mềm. Tiếp theo, nó cũng được ghi nhận về việc đưa các chức năng vốn ít được quen biết vào thực tế, có khi còn vượt cả ra bên ngoài nền tảng Java nữa. Thành quả của việc này là nó đã tạo nên một bộ khung, cung cấp một mô hình nhất quán và làm cho nó có thể áp dụng vào hầu hết các loại ứng dụng được tạo trên nền tảng Java ngày nay. Bộ khung Spring được coi như thực thi một cách làm việc dựa trên những thói quen thực hành tốt nhất và những tiêu chuẩn công nghiệp, và đồng thời tạo cơ hội cho những lĩnh vực trong Java sử dụng nó 2.2.1 IoC(Inversion of Control) Cung cấp khung để cài đặt và quản lý các đối tượng Java. Khung này có nhiệm vụ quản lý vòng đời của đối tượng: tạo đối tượng, gọi các hàm khởi tạo, cấu hình các đối tượng bằng cách nối nó lại với nhau. Đối tượng được tạo bởi khung này được gọi là đối tượng được quản lý hay Bean. Thông thường Bean được định nghĩa trong file cấu hình XML 2.2.2 DI(Dependency Injection) Là một mẫu hình mà trong đó khung chứa truyền giao các đối tượng cho nhau bằng tên của chúng, thông qua những phương pháp khởi tạo (constructor), các đặc tính (properties) hoặc các phương pháp chế xuất (factory methods / Factory method pattern).Ví dụ: 16 Có thể cấu hình properties, constructor bằng XML: example org.springframework.web.servlet.DispatcherServlet 1 example *.form Trong ví dụ trên, tất cả các request kết thúc với .form sẽ được xử lí bởi 'example' DispatcherServlet. Đây chỉ là bước khởi đầu để cấu hình trong sự thiết lập Spring Web MVC...Những bean khác nhau được sử dụng bởi Spring WebMVC framework (trên và DispatcherServlet trên của chính nó) cầu được cấu hình ngay. 20 Framework sẽ, trên sự khởi tạo của một DispatcherServlet, tìm kiếm một tên file [servlet-name]-servlet.xml trong thư mục WEB-INF của ứng dụng web của chúng ta và tạo các bean được định nghĩa ở đó (overriding những sự định nghĩa của một vài bean đượcđịnh nghĩa cùng tên trong phạm vi global). Spring DispatcherServlet có một sự ghép nối với các bean đặc biệt, nó dùng để có thể xử lí các request và tạo ra những viewthích hợp. Những bean đó được bao gồm bên trong Spring framework và có thể được cấu hình trong WebApplicationContext, chỉ như một vài bean khác cần được cấu hình. Mỗi cái bean này được mô tả chi tiết hơn bên dưới. Bây giờ, chúng ta sẽ chỉ đề cậpđến chúng, vừa để chúng ta biết chúng tồn tại và có thể cho phép chúng ta nói về DispatcherServlet. Hầu hết các bean, có thể thấyđược mặc định được cung cấp vì thế chúng ta không (initially) phải lo lằng về làm sao cấu hình chúng. Khi một DispatcherServlet được cài đặt cho việc sử dụng và một request đến DispatcherServlet đặt biệt, người ta bảo rằngDispatcherServlet bắt đầu xử lí các request. Danh sách các mô tả sau mô tả đầy đủ một request đến khi được sử lí bởi mộtDispatcherServlet: 1. WebApplicationContext được tìm kiếm và bao trong request như một thuộc tính để cho controller và những nguyên tốkhác trong quá trình xử lí sử dụng. Nó được bao mặc định bởi khóa DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE. 2. Vị trí của locale resolver được bao với request để các nguyên tố trong trong quá trình xử lí giải quyết locale để sử dụngkhi xử lí request (tạo view, chuẩn bị dữ liệu,v.v..) nếu chúng ta không sử dụng resolver, nó sẽ không gây ảnh hưởng gì cả, vìthế nếu chúng ta không cần locale giải quyết , chúng ta không phải xử dụng nó. 3. Theme resolver được bao với request để các yếu tố như là các views xác đinh theme nào được sử dụng. Themeresolver không ảnh gì cả nếu chúng ta không dùng nó, vì thế chúng ta không cần theme thì chỉ cần chúng ta làm ngơ với nó. 4. Nếu một multipart resolver được đặc tả, request được duyệt cho các multipart; nếu các multipart được tìm thấy, requestđược bao phủ trong một MultipartHttpServletRequest cho quá trình xử lí xa hơn nữa bởi các yếu tố bên trong xử lí. (XemSection 13.8.2, “Using the MultipartResolver” thêm thông tin về multipart handling). 5. Một handler thích hợp được tìm kiếm. Nếu một handler được tìm thấy, sự xử lí buộc liên kết với handler (cácpreprocessor, các postprocessor, và controller) sẽ được thực thi để chuẩn bị một a model (cho sự phát sinh [render]).
- Xem thêm -

Tài liệu liên quan