- Sản phẩm & Dịch vụSản phẩm & Dịch vụ
- Giải phápGiải pháp
- Bảng giáBảng giá
- Công tyCông ty
- Tài liệuTài liệu
vi
vi
Chuyên mục với các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.
Technical Writer
I have over 5 years of experience writing technical documentation for tech products, making them accessible and user-friendly. My focus is always on providing clear and precise information. @#@ Tôi đã có hơn 5 năm kinh nghiệm viết tài liệu kỹ thuật cho các sản phẩm công nghệ, giúp người dùng dễ dàng tiếp cận và sử dụng. Tôi luôn tập trung vào việc cung cấp thông tin chính xác và dễ hiểu.
Thảo luận (0)
Đăng nhập để thảo luận
HQL hay Hibernate Query Language là ngôn ngữ truy vấn hướng đối tượng của Hibernate Framework. HQL khá giống với SQL, chỉ khác ở chỗ nó sử dụng Objects thay vì tên bảng, nhờ đó nó gần gũi hơn với lập trình hướng đối tượng.

HQL không phân biệt chữ hoa – chữ thường, ngoại trừ tên java class và tên biến. Ví dụ: SeLeCT, sELEct hay SELECT đều giống nhau. Nhưng com.journaldev.model.Employee thì khác với com.journaldev.model.EMPLOYEE. Một số clause thường được HQL hỗ trợ bao gồm:
from Employee tương đương với select * from Employee. Chúng ta cũng có thể tạo alias như: from Employee emp hoặc from Employee as emp.select e.name, a.city from Employee e INNER JOIN e.address a.Trong truy vấn này, class Employee phải có một biến tên là address. Chúng ta sẽ tìm hiểu rõ hơn trong phần ví dụ code.Trong ví dụ này, tôi sử dụng MySQL database. Script dưới đây sẽ tạo 2 bảng Employee và Address. Hai bảng này có quan hệ one-to-one mapping và tôi sẽ chèn một số dữ liệu mẫu để minh họa.
CREATE TABLE `Employee` ( `emp_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `emp_name` varchar(20) NOT NULL, `emp_salary` double(10,0) NOT NULL DEFAULT '0', PRIMARY KEY (`emp_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;CREATE TABLE
Address(emp_idint(11) unsigned NOT NULL,address_line1varchar(50) NOT NULL DEFAULT '',zipcodevarchar(10) DEFAULT NULL,cityvarchar(20) DEFAULT NULL, PRIMARY KEY (emp_id), CONSTRAINTemp_fk_1FOREIGN KEY (emp_id) REFERENCESEmployee(emp_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO
Employee(emp_id,emp_name,emp_salary) VALUES (1, 'Pankaj', 100), (2, 'David', 200), (3, 'Lisa', 300), (4, 'Jack', 400);INSERT INTO
Address(emp_id,address_line1,zipcode,city) VALUES (1, 'Albany Dr', '95129', 'San Jose'), (2, 'Arques Ave', '95051', 'Santa Clara'), (3, 'BTM 1st Stage', '560100', 'Bangalore'), (4, 'City Centre', '100100', 'New Delhi');commit;
Hãy tạo một Maven project trong Eclipse hoặc bất kỳ IDE nào bạn đang sử dụng. Dự án hoàn chỉnh của chúng ta sẽ trông giống như hình dưới đây.

File pom.xml cuối cùng của chúng ta sẽ chứa các dependencies cho Hibernate và MySQL driver.
<project xmlns="<https://maven.apache.org/POM/4.0.0>" xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>" xsi:schemaLocation="<https://maven.apache.org/POM/4.0.0> <https://maven.apache.org/xsd/maven-4.0.0.xsd>"> <modelVersion>4.0.0</modelVersion> <groupId>com.journaldev.hibernate</groupId> <artifactId>HQLExample</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.5.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.5</version> </dependency> </dependencies> </project>
File hibernate configuration XML của chúng ta chứa các thuộc tính liên quan đến kết nối database và các mapping classes. Trong ví dụ này, tôi sẽ sử dụng annotations cho Hibernate mapping. hibernate.cfg.xml code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"<https://hibernate.org/dtd/hibernate-configuration-3.0.dtd>">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">pankaj123</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">pankaj</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.journaldev.hibernate.model.Employee"/>
<mapping class="com.journaldev.hibernate.model.Address"/>
</session-factory>
</hibernate-configuration>
Chúng ta có một utility class để cấu hình Hibernate SessionFactory.
package com.journaldev.hibernate.util;import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry;
public class HibernateUtil {
private static SessionFactory sessionFactory; private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml Configuration configuration = new Configuration(); configuration.configure("hibernate.cfg.xml"); System.out.println("Hibernate Configuration loaded"); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); System.out.println("Hibernate serviceRegistry created"); SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); return sessionFactory; } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); ex.printStackTrace(); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { if(sessionFactory == null) sessionFactory = buildSessionFactory(); return sessionFactory; }}
Các model classes của chúng ta với JPA annotations sẽ trông như dưới đây.
package com.journaldev.hibernate.model;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
@Entity @Table(name = "EMPLOYEE") public class Employee {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "emp_id") private long id; @Column(name = "emp_name") private String name; @Column(name = "emp_salary") private double salary; @OneToOne(mappedBy = "employee") @Cascade(value = org.hibernate.annotations.CascadeType.ALL) private Address address; public long getId() { return id; } public void setId(long id) { this.id = id; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; }}
package com.journaldev.hibernate.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
@Entity
@Table(name = "ADDRESS")
public class Address {
@Id
@Column(name = "emp_id", unique = true, nullable = false)
@GeneratedValue(generator = "gen")
@GenericGenerator(name = "gen", strategy = "foreign",
parameters = { @Parameter(name = "property", value = "employee") })
private long id;
@Column(name = "address_line1")
private String addressLine1;
@Column(name = "zipcode")
private String zipcode;
@Column(name = "city")
private String city;
@OneToOne
@PrimaryKeyJoinColumn
private Employee employee;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
Hãy cùng xem cách sử dụng HQL trong các chương trình Java.
package com.journaldev.hibernate.main;import java.util.Arrays; import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Employee; import com.journaldev.hibernate.util.HibernateUtil;
public class HQLExamples {
@SuppressWarnings("unchecked") public static void main(String[] args) { //Prep work SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.getCurrentSession(); //HQL example - Get All Employees Transaction tx = session.beginTransaction(); Query query = session.createQuery("from Employee"); List<Employee> empList = query.list(); for(Employee emp : empList){ System.out.println("List of Employees::"+emp.getId()+","+emp.getAddress().getCity()); } //HQL example - Get Employee with id query = session.createQuery("from Employee where id= :id"); query.setLong("id", 3); Employee emp = (Employee) query.uniqueResult(); System.out.println("Employee Name="+emp.getName()+", City="+emp.getAddress().getCity()); //HQL pagination example query = session.createQuery("from Employee"); query.setFirstResult(0); //starts with 0 query.setFetchSize(2); empList = query.list(); for(Employee emp4 : empList){ System.out.println("Paginated Employees::"+emp4.getId()+","+emp4.getAddress().getCity()); } //HQL Update Employee query = session.createQuery("update Employee set name= :name where id= :id"); query.setParameter("name", "Pankaj Kumar"); query.setLong("id", 1); int result = query.executeUpdate(); System.out.println("Employee Update Status="+result); //HQL Delete Employee, we need to take care of foreign key constraints too query = session.createQuery("delete from Address where id= :id"); query.setLong("id", 4); result = query.executeUpdate(); System.out.println("Address Delete Status="+result); query = session.createQuery("delete from Employee where id= :id"); query.setLong("id", 4); result = query.executeUpdate(); System.out.println("Employee Delete Status="+result); //HQL Aggregate function examples query = session.createQuery("select sum(salary) from Employee"); double sumSalary = (Double) query.uniqueResult(); System.out.println("Sum of all Salaries= "+sumSalary); //HQL join examples query = session.createQuery("select e.name, a.city from Employee e " + "INNER JOIN e.address a"); List<Object[]> list = query.list(); for(Object[] arr : list){ System.out.println(Arrays.toString(arr)); } //HQL group by and like example query = session.createQuery("select e.name, sum(e.salary), count(e)" + " from Employee e where e.name like '%i%' group by e.name"); List<Object[]> groupList = query.list(); for(Object[] arr : groupList){ System.out.println(Arrays.toString(arr)); } //HQL order by example query = session.createQuery("from Employee e order by e.id desc"); empList = query.list(); for(Employee emp3 : empList){ System.out.println("ID Desc Order Employee::"+emp3.getId()+","+emp3.getAddress().getCity()); } //rolling back to save the test data tx.rollback(); //closing hibernate resources sessionFactory.close(); }}
Lưu ý rằng tôi đang sử dụng HQL cho các thao tác Select, Update và Delete. Ví dụ này cũng minh họa cách dùng HQL Join và các HQL Aggregate functions. Khi tôi chạy chương trình ví dụ HQL ở trên, chúng ta sẽ nhận được output như sau.
May 22, 2014 1:55:37 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
May 22, 2014 1:55:37 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.5.Final}
May 22, 2014 1:55:37 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
May 22, 2014 1:55:37 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
May 22, 2014 1:55:37 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: hibernate.cfg.xml
May 22, 2014 1:55:37 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: hibernate.cfg.xml
May 22, 2014 1:55:37 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
Hibernate Configuration loaded
Hibernate serviceRegistry created
May 22, 2014 1:55:37 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
May 22, 2014 1:55:37 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/TestDB]
May 22, 2014 1:55:37 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=pankaj, password=****}
May 22, 2014 1:55:37 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
May 22, 2014 1:55:37 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
May 22, 2014 1:55:37 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
May 22, 2014 1:55:37 PM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
May 22, 2014 1:55:38 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
May 22, 2014 1:55:38 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
List of Employees::1,San Jose
List of Employees::2,Santa Clara
List of Employees::3,Bangalore
List of Employees::4,New Delhi
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ where employee0_.emp_id=?
Employee Name=Lisa, City=Bangalore
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_
Paginated Employees::1,San Jose
Paginated Employees::2,Santa Clara
Paginated Employees::3,Bangalore
Paginated Employees::4,New Delhi
Hibernate: update EMPLOYEE set emp_name=? where emp_id=?
Employee Update Status=1
Hibernate: delete from ADDRESS where emp_id=?
Address Delete Status=1
Hibernate: delete from EMPLOYEE where emp_id=?
Employee Delete Status=1
Hibernate: select sum(employee0_.emp_salary) as col_0_0_ from EMPLOYEE employee0_
Sum of all Salaries= 600.0
Hibernate: select employee0_.emp_name as col_0_0_, address1_.city as col_1_0_ from EMPLOYEE employee0_ inner join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id
[Pankaj Kumar, San Jose]
[David, Santa Clara]
[Lisa, Bangalore]
Hibernate: select employee0_.emp_name as col_0_0_, sum(employee0_.emp_salary) as col_1_0_, count(employee0_.emp_id) as col_2_0_ from EMPLOYEE employee0_ where employee0_.emp_name like '%i%' group by employee0_.emp_name
[David, 200.0, 1]
[Lisa, 300.0, 1]
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ order by employee0_.emp_id desc
ID Desc Order Employee::3,Bangalore
ID Desc Order Employee::2,Santa Clara
ID Desc Order Employee::1,San Jose
May 22, 2014 1:55:38 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:mysql://localhost/TestDB]
Lưu ý rằng sau khi thực hiện thao tác delete, các thao tác tiếp theo sẽ không còn hiển thị dữ liệu của record đó nữa (ví dụ: tổng lương chỉ còn 600). Tuy nhiên, do tôi đang rollback transaction, nên dữ liệu trong bảng thực tế không thay đổi. Nếu bạn chỉnh code để commit transaction, thì sự thay đổi sẽ được phản ánh vào các bảng trong database.
Cá nhân tôi không thích sử dụng HQL query quá nhiều, bởi vì như bạn thấy, chúng ta cần phải chú ý đến ánh xạ bảng (table mappings) trong code. Nếu dùng Session để xóa các đối tượng Employee, thì record sẽ bị xóa ở cả hai bảng.