Thông thường, khi cần thao tác đến một database bất kỳ, chúng ta phải viết câu SQL dựa trên thông tin của các cột, các bảng trong database đó và có thể đối với mỗi loại database khác nhau, syntax của câu SQL cũng khác nhau. Để loại bỏ những nhược điểm này, các bạn có thể sử dụng JPA Query Language (JPQL). Cụ thể như thế nào? Chúng ta hãy cùng nhau tìm hiểu trong bài viết này nhé các bạn.
Đầu tiên, mình sẽ tạo một Maven project để làm ví dụ:
Vì mình sẽ sử dụng JPA với implementation của Hibernate, do đó, mình sẽ thêm Hibernate dependencies như sau:
1 2 3 4 5 6 7 8 9 10 |
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.12.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>5.2.12.Final</version> </dependency> |
Project Lombok:
1 2 3 4 5 6 |
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> <scope>provided</scope> </dependency> |
Điều đầu tiên mình cần nói với các bạn về JPA Query Language đó là nó cho phép chúng ta định nghĩa các câu query dựa trên các entity chứ không dựa vào tên các cột, các bảng trong database.
Cấu trúc và cú pháp của JPA Query Language thì rất tương tự như cấu trúc và cú pháp của câu SQL. Ví dụ như đối với câu lệnh SELECT, cú pháp của JPA Query Language như sau:
1 2 3 4 |
SELECT ... FROM ... [WHERE ...] [GROUP BY ... [HAVING ...]] [ORDER BY ...] |
hay với DELETE,
1 |
DELETE FROM ... [WHERE ...] |
UPDATE
1 |
UPDATE ... SET ... [WHERE ...] |
Điều này giúp chúng ta dễ dàng định nghĩa các câu query sử dụng JPA Query Language nhưng các bạn cũng nên nhớ một điều là: mặc dù chúng ta định nghĩa các câu query sử dụng các entity nhưng trong thực tế, lúc chạy, Hibernate hay bất kỳ thư viện nào implement JPA đều transform những câu query đó sang những câu SQL dành cho database với tên cột, tên bảng của database đó.
Giả sử bây giờ mình sẽ sử dụng MySQL database làm ví dụ cho bài viết này. Mình có 1 table như sau:
1 2 3 4 5 |
CREATE TABLE `clazz` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
Entity Clazz như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.huongdanjava.jpa; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import lombok.Getter; import lombok.Setter; @Entity @Table @Getter @Setter public class Clazz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String name; } |
Để làm việc với MySQL database, chúng ta cần sử dụng MySQL Driver dependency:
1 2 3 4 5 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> |
Tập tin cấu hình của JPA dành cho MySQL database:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence_2_1.xsd"> <persistence-unit name="jpaexample" transaction-type="RESOURCE_LOCAL"> <class>com.huongdanjava.jpa.Clazz</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa_example" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="123456" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.use_sql_comments" value="true" /> </properties> </persistence-unit> </persistence> |
Trong database, mình đang có những dữ liệu như sau:
Giờ mình sẽ thử sử dụng JPA Query Language để lấy thông tin từ bảng clazz ra thử xem sao nha các bạn.
Đầu tiên, chúng ta sẽ lấy đối tượng EntityManager trước:
1 2 |
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); EntityManager em = emf.createEntityManager(); |
Tiếp theo chúng ta sẽ sử dụng đối tượng EntityManager để lấy đối tượng Query dựa vào thông tin của entity Clazz như sau:
1 |
Query query = em.createQuery("SELECT c FROM Clazz c"); |
Trong dòng code trên, chúng ta đã truyền cho phương thức createQuery() một câu JPA Query Language. Các bạn có thấy nó giống câu SQL mà chúng ta hay dùng để truy vấn database không? 😀 Chỉ có cái khác là lúc này nó sử dụng tên của entity của table clazz chứ không phải là tên của table clazz.
Các bạn cũng thấy là ở đây chúng ta đã đặt cho entity Clazz một alias c giống như trong câu SQL. Alias này các bạn có thể sử dụng giống như một biến trong Java, nghĩa là nếu muốn lấy thông tin các thuộc tính của entity Clazz, các bạn có thể sử dụng “c.<tên_của_thuộc_tính>”. Ví dụ như nếu các bạn muốn lấy thông tin column name trong table clazz thôi thì có thể viết lại câu JPA Query Language như sau:
1 |
SELECT c.name FROM Clazz c |
Bây giờ, sau khi đã có đối tượng Query rồi, các bạn có thể sử dụng nó để lấy kết quả mà các bạn muốn như sau:
1 |
List<Clazz> resultList = query.getResultList(); |
Đối tượng Query này có rất nhiều method, tuỳ theo câu JPA Query Language của bạn là gì thì các bạn hãy sử dụng method của nó cho phù hợp. Ở đây, câu JPA Query Language của mình là lấy tất cả các record trong bảng clazz, do đó mình sử dụng method getResultList().
Sau khi lấy xong, thì các bạn có thể in ra kết quả với đoạn code sau:
1 |
resultList.stream().forEach(c -> System.out.println(c.getName())); |
Kết quả:
Toàn bộ code như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.huongdanjava.jpa; import javax.persistence.*; import java.util.List; public class Application { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); EntityManager em = emf.createEntityManager(); Query query = em.createQuery("SELECT c FROM Clazz c"); List<Clazz> resultList = query.getResultList(); resultList.stream().forEach(c -> System.out.println(c.getName())); } } |
Đào Hà
Query query = em.createQuery(“SELECT c FROM Clazz c”);
Câu này là truy vấn từ entity Clazz. Vậy bạn cho mình hỏi chỗ nào mapping entity Clazz với table Clazz trong database, để java có thể biết là bạn muốn truy vấn từ table Clazz trong database.
Cảm ơn
Khanh Nguyen
Ủa, trong bài viết có định nghĩa class Clazz mà bạn!
Đào Hà
Mình nhìn thấy rồi bạn ạ. Nhưng mình đang k biết là chỗ nào mapping class Clazz với table Clazz trong database, bạn chỉ cho mình được không
Khanh Nguyen
Mình có khai báo 2 annotation @Entity và @Table của JPA đó bạn. Bạn tìm hiểu thêm về JPA nhé! https://huongdanjava.com/vi/java-persistence-api
huynh
Anh ơi khi xong một bài viết anh có thể để lại source hông ạ?
Khanh Nguyen
Tất cả các ví dụ của Hướng Dẫn Java, anh đều commit lên GitHub hết em nhé!
Check tại đây: https://github.com/huongdanjavacom/huongdanjava.com
huynh
Em cảm ơn nhé! Sorry anh vì em không tìm mà đã hỏi a!