HQL ou Linguagem de Consulta do Hibernate é a linguagem de consulta orientada a objetos do Framework Hibernate. HQL é muito semelhante ao SQL, exceto que usamos Objetos em vez de nomes de tabelas, o que o torna mais próximo da programação orientada a objetos.
Linguagem de Consulta do Hibernate – HQL
HQL e Sensibilidade a Maiúsculas e Minúsculas: HQL não diferencia maiúsculas de minúsculas, exceto para nomes de classes Java e variáveis. Assim,
SeLeCT
é o mesmo que sELEct
é o mesmo que SELECT
, mas com.journaldev.model.Employee
não é o mesmo que com.journaldev.model.EMPLOYEE
. Algumas das cláusulas comumente suportadas em HQL são:
- HQL From: HQL From é o mesmo que a cláusula select no SQL,
from Employee
é o mesmo queselect * from Employee
. Também podemos criar aliases, comofrom Employee emp
oufrom Employee as emp
. - HQL Join: HQL suporta inner join, left outer join, right outer join e full join. Por exemplo,
select e.name, a.city from Employee e INNER JOIN e.address a
. Nesta consulta, a classe Employee deve ter uma variável chamada address. Vamos analisar isso no código de exemplo. - Funções de Agregação: O HQL suporta funções de agregação comumente utilizadas, como count(*), count(distinct x), min(), max(), avg() e sum().
- Expressões: O HQL suporta expressões aritméticas (+, -, *, /), operadores binários de comparação (=, >=, <=, <>, !=, like), operações lógicas (and, or, not) etc.
- O HQL também suporta as cláusulas order by e group by.
- O HQL também permite subconsultas, assim como consultas SQL.
- O HQL suporta DDL, DML e execução de stored procedures.
Vamos dar uma olhada em um exemplo simples de uso do HQL em nosso programa.
Exemplo de Configuração do Banco de Dados em HQL
I am using MySQL database for my example, below script will create two tables Employee and Address. They have one-to-one mapping and I am inserting some demo data for my example.
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_id` int(11) unsigned NOT NULL,
`address_line1` varchar(50) NOT NULL DEFAULT '',
`zipcode` varchar(10) DEFAULT NULL,
`city` varchar(20) DEFAULT NULL,
PRIMARY KEY (`emp_id`),
CONSTRAINT `emp_fk_1` FOREIGN KEY (`emp_id`) REFERENCES `Employee` (`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;
Crie um projeto Maven no Eclipse ou na IDE que estiver usando; nosso projeto final terá a aparência da imagem abaixo.
Dependências do Hibernate no Maven
Nosso arquivo pom.xml final contém as dependências para o Hibernate e o driver MySQL.
<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>
Configuração XML do Hibernate
O nosso ficheiro de configuração XML do Hibernate contém propriedades relacionadas com a ligação à base de dados e classes de mapeamento. Vou utilizar anotações para o mapeamento do Hibernate. Código hibernate.cfg.xml:
<?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>
Classe Utilitária do SessionFactory do Hibernate
Temos uma classe utilitária para configurar o SessionFactory do Hibernate.
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 {
// Criar o SessionFactory a partir do 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;
}
}
Classes de Modelo com mapeamento baseado em anotações
As nossas classes de modelo com anotações JPA parecem-se com o seguinte.
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;
}
}
Classe de Teste de Exemplo HQL
Vamos ver como usar HQL em programas 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) {
//Trabalho preparatório
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
//Exemplo de HQL - Obter todos os funcionários
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Employee");
List empList = query.list();
for(Employee emp : empList){
System.out.println("List of Employees::"+emp.getId()+","+emp.getAddress().getCity());
}
//Exemplo de HQL - Obter funcionário com 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());
//Exemplo de paginação de HQL
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());
}
//Atualizar funcionário de HQL
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);
//Excluir funcionário de HQL, precisamos cuidar das restrições de chave estrangeira também
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);
//Exemplos de função de agregação de HQL
query = session.createQuery("select sum(salary) from Employee");
double sumSalary = (Double) query.uniqueResult();
System.out.println("Sum of all Salaries= "+sumSalary);
//Exemplos de junção de HQL
query = session.createQuery("select e.name, a.city from Employee e "
+ "INNER JOIN e.address a");
List
Observe que estou usando HQL para operações de Seleção, Atualização e Exclusão. Ele também mostra como usar Junção HQL e Funções de Agregação de HQL. Quando executo o programa de exemplo de HQL acima, obtemos a seguinte saída.
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]
Observe que uma vez que a operação de exclusão é realizada, operações adicionais não mostram os dados desse registro (a soma do salário é 600). No entanto, estou revertendo a transação, então os dados na tabela permanecerão inalterados. Altere o código para confirmar a transação e isso será refletido nas tabelas do banco de dados. Não gosto muito de usar consulta HQL porque, como você pode ver, precisamos cuidar dos mapeamentos de tabela em nosso código. Se usarmos a Sessão para excluir o objeto Funcionário, ele excluirá o registro de ambas as tabelas. Você pode baixar o projeto de exemplo de consulta HQL no link abaixo e tentar mais exemplos.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-query-language-hql-example-tutorial