JPA - JPQL
Este capítulo fala sobre JPQL e como ele funciona com unidades de persistência. Neste capítulo, os exemplos seguem a mesma hierarquia de pacotes, que usamos no capítulo anterior da seguinte maneira:
Linguagem Java Persistence Query
JPQL é Java Persistence Query Language definida na especificação JPA. É usado para criar consultas em entidades para armazenar em um banco de dados relacional. JPQL é desenvolvido com base na sintaxe SQL. Mas isso não afetará o banco de dados diretamente.
JPQL pode recuperar informações ou dados usando a cláusula SELECT, pode fazer atualizações em massa usando as cláusulas UPDATE e DELETE. A API EntityManager.createQuery () oferece suporte para linguagem de consulta.
Estrutura de Consulta
A sintaxe JPQL é muito semelhante à sintaxe SQL. Ter a sintaxe semelhante ao SQL é uma vantagem porque o SQL é uma linguagem de consulta estruturada simples e muitos desenvolvedores a estão usando em aplicativos. O SQL funciona diretamente em tabelas, registros e campos de banco de dados relacional, enquanto JPQL funciona com classes e instâncias Java.
Por exemplo, uma consulta JPQL pode recuperar um objeto de entidade em vez de conjunto de resultados de campo do banco de dados, como no SQL. A estrutura da consulta JPQL da seguinte maneira.
SELECT ... FROM ...
[WHERE ...]
[GROUP BY ... [HAVING ...]]
[ORDER BY ...]
A estrutura das consultas JPQL DELETE e UPDATE é mais simples da seguinte maneira.
DELETE FROM ... [WHERE ...]
UPDATE ... SET ... [WHERE ...]
Funções escalares e agregadas
Funções escalares retornam valores resultantes com base em valores de entrada. As funções agregadas retornam os valores resultantes calculando os valores de entrada.
Siga o mesmo exemplo de gerenciamento de funcionários usado nos capítulos anteriores. Aqui, vamos percorrer as classes de serviço usando funções escalares e agregadas de JPQL.
Vamos supor que a tabela jpadb.employee contém os seguintes registros.
Eid | Ename | Salário | Grau |
---|---|---|---|
1201 | Gopal | 40.000 | Gerente técnico |
1202 | Manisha | 40.000 | Leitor de Provas |
1203 | Masthanvali | 40.000 | Escritor técnico |
1204 | Satish | 30000 | Escritor técnico |
1205 | Krishna | 30000 | Escritor técnico |
1206 | Kiran | 35000 | Leitor de Provas |
Crie uma classe chamada ScalarandAggregateFunctions.java debaixo com.tutorialspoint.eclipselink.service pacote da seguinte forma.
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class ScalarandAggregateFunctions {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
//Scalar function
Query query = entitymanager.
createQuery("Select UPPER(e.ename) from Employee e");
List<String> list = query.getResultList();
for(String e:list) {
System.out.println("Employee NAME :"+e);
}
//Aggregate function
Query query1 = entitymanager.createQuery("Select MAX(e.salary) from Employee e");
Double result = (Double) query1.getSingleResult();
System.out.println("Max Employee Salary :" + result);
}
}
Após a compilação e execução do programa acima, você obterá a saída no painel do console do Eclipse IDE da seguinte forma:
Employee NAME :GOPAL
Employee NAME :MANISHA
Employee NAME :MASTHANVALI
Employee NAME :SATISH
Employee NAME :KRISHNA
Employee NAME :KIRAN
ax Employee Salary :40000.0
Entre, E, Palavras-chave semelhantes
'Entre', 'E' e 'Como' são as principais palavras-chave do JPQL. Essas palavras-chave são usadas após a cláusula Where em uma consulta.
Crie uma classe chamada BetweenAndLikeFunctions.java debaixo com.tutorialspoint.eclipselink.service pacote da seguinte forma:
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;
public class BetweenAndLikeFunctions {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
//Between
Query query = entitymanager.createQuery( "Select e " + "from Employee e " + "where e.salary " + "Between 30000 and 40000" );
List<Employee> list=(List<Employee>)query.getResultList( );
for( Employee e:list ){
System.out.print("Employee ID :" + e.getEid( ));
System.out.println("\t Employee salary :" + e.getSalary( ));
}
//Like
Query query1 = entitymanager.createQuery("Select e " + "from Employee e " + "where e.ename LIKE 'M%'");
List<Employee> list1=(List<Employee>)query1.getResultList( );
for( Employee e:list1 ) {
System.out.print("Employee ID :"+e.getEid( ));
System.out.println("\t Employee name :"+e.getEname( ));
}
}
}
Após a compilação e execução do programa acima, você obterá a saída no painel do console do Eclipse IDE da seguinte forma:
Employee ID :1201 Employee salary :40000.0
Employee ID :1202 Employee salary :40000.0
Employee ID :1203 Employee salary :40000.0
Employee ID :1204 Employee salary :30000.0
Employee ID :1205 Employee salary :30000.0
Employee ID :1206 Employee salary :35000.0
Employee ID :1202 Employee name :Manisha
Employee ID :1203 Employee name :Masthanvali
Encomenda
Para solicitar os registros em JPQL, usamos a cláusula ORDER BY. O uso dessa cláusula é igual ao uso em SQL, mas trata de entidades. Siga o exemplo do pedido.
Crie uma classe Ordering.java em com.tutorialspoint.eclipselink.service pacote da seguinte forma:
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;
public class Ordering {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
//Between
Query query = entitymanager.createQuery( "Select e " + "from Employee e " + "ORDER BY e.ename ASC" );
List<Employee> list = (List<Employee>)query.getResultList( );
for( Employee e:list ) {
System.out.print("Employee ID :" + e.getEid( ));
System.out.println("\t Employee Name :" + e.getEname( ));
}
}
}
Após a compilação e execução do programa acima, você obterá a saída no painel do console do Eclipse IDE da seguinte forma:
Employee ID :1201 Employee Name :Gopal
Employee ID :1206 Employee Name :Kiran
Employee ID :1205 Employee Name :Krishna
Employee ID :1202 Employee Name :Manisha
Employee ID :1203 Employee Name :Masthanvali
Employee ID :1204 Employee Name :Satish
Consultas nomeadas
Uma anotação @NamedQuery é definida como uma consulta com uma string de consulta predefinida e imutável. Em vez de consultas dinâmicas, o uso de consultas nomeadas pode melhorar a organização do código, separando as strings de consulta JPQL do POJO. Ele também passa os parâmetros de consulta em vez de incorporar literais dinamicamente na string de consulta e resulta em consultas mais eficientes.
Primeiro de tudo, adicione a anotação @NamedQuery à classe de entidade Employee chamada Employee.java debaixo com.tutorialspoint.eclipselink.entity pacote da seguinte forma:
package com.tutorialspoint.eclipselink.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@Table
@NamedQuery(query = "Select e from Employee e where e.eid = :id", name = "find employee by id")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int eid;
private String ename;
private double salary;
private String deg;
public Employee(int eid, String ename, double salary, String deg) {
super( );
this.eid = eid;
this.ename = ename;
this.salary = salary;
this.deg = deg;
}
public Employee( ) {
super();
}
public int getEid( ) {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String getEname( ) {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public double getSalary( ) {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDeg( ) {
return deg;
}
public void setDeg(String deg) {
this.deg = deg;
}
@Override
public String toString() {
return "Employee [eid=" + eid + ", ename=" + ename + ", salary=" + salary + ", deg=" + deg + "]";
}
}
Crie uma classe chamada NamedQueries.java debaixo com.tutorialspoint.eclipselink.service pacote da seguinte forma:
package com.tutorialspoint.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.tutorialspoint.eclipselink.entity.Employee;
public class NamedQueries {
public static void main( String[ ] args ) {
EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
Query query = entitymanager.createNamedQuery("find employee by id");
query.setParameter("id", 1204);
List<Employee> list = query.getResultList( );
for( Employee e:list ){
System.out.print("Employee ID :" + e.getEid( ));
System.out.println("\t Employee Name :" + e.getEname( ));
}
}
}
Após a compilação e execução do programa acima, você obterá a saída no painel do console do Eclipse IDE da seguinte forma:
Employee ID :1204 Employee Name :Satish
Depois de adicionar todas as classes acima, a hierarquia do pacote é mostrada da seguinte forma:
Carregamento ansioso e lento
O conceito principal do JPA é fazer uma cópia duplicada do banco de dados na memória cache. Durante a transação com o banco de dados, primeiro isso afetará os dados duplicados e, apenas quando for confirmado usando o gerenciador de entidade, as alterações serão efetuadas no banco de dados.
Existem duas maneiras de obter registros do banco de dados - eager fetch e lazy fetch.
Eager fetch
Buscando o registro inteiro enquanto encontra o registro usando a chave primária.
Preguiçoso
Ele verifica a disponibilidade ou o notifica com a chave primária, se houver. Mais tarde, se você chamar qualquer um dos métodos getter dessa entidade, ele buscará o todo.
Mas a busca lenta é possível quando você tenta buscar o registro pela primeira vez. Dessa forma, uma cópia de todo o registro já está armazenada na memória cache. Em termos de desempenho, a busca lenta é preferível.