JPA - JPQL
บทนี้จะบอกคุณเกี่ยวกับ JPQL และวิธีการทำงานกับหน่วยการคงอยู่ ในบทนี้ตัวอย่างจะเป็นไปตามลำดับชั้นของแพ็กเกจเดียวกันซึ่งเราใช้ในบทก่อนหน้าดังนี้:
ภาษา Java Persistence Query
JPQL คือ Java Persistence Query Language ที่กำหนดไว้ในข้อกำหนดของ JPA ใช้เพื่อสร้างแบบสอบถามกับเอนทิตีเพื่อจัดเก็บในฐานข้อมูลเชิงสัมพันธ์ JPQL ได้รับการพัฒนาโดยใช้ไวยากรณ์ SQL แต่จะไม่ส่งผลกระทบต่อฐานข้อมูลโดยตรง
JPQL สามารถดึงข้อมูลหรือข้อมูลโดยใช้คำสั่ง SELECT สามารถทำการอัปเดตจำนวนมากโดยใช้ UPDATE clause และ DELETE clause EntityManager.createQuery () API จะรองรับภาษาในการสืบค้น
โครงสร้างแบบสอบถาม
ไวยากรณ์ของ JPQL นั้นคล้ายกับไวยากรณ์ของ SQL มาก การมี SQL เหมือนกับไวยากรณ์ถือเป็นข้อได้เปรียบเนื่องจาก SQL เป็นภาษาแบบสอบถามที่มีโครงสร้างเรียบง่ายและมีนักพัฒนาจำนวนมากใช้ในแอปพลิเคชัน SQL ทำงานโดยตรงกับตารางฐานข้อมูลเชิงสัมพันธ์เรกคอร์ดและฟิลด์ในขณะที่ JPQL ทำงานร่วมกับคลาสและอินสแตนซ์ Java
ตัวอย่างเช่นแบบสอบถาม JPQL สามารถดึงวัตถุเอนทิตีแทนที่จะเป็นผลลัพธ์ของฟิลด์ที่กำหนดจากฐานข้อมูลเช่นเดียวกับ SQL โครงสร้างแบบสอบถาม JPQL ดังต่อไปนี้
SELECT ... FROM ...
[WHERE ...]
[GROUP BY ... [HAVING ...]]
[ORDER BY ...]
โครงสร้างของแบบสอบถาม JPQL DELETE และ UPDATE นั้นง่ายกว่าดังนี้
DELETE FROM ... [WHERE ...]
UPDATE ... SET ... [WHERE ...]
ฟังก์ชั่น Scalar และ Aggregate
ฟังก์ชัน Scalar จะส่งคืนค่าผลลัพธ์ตามค่าอินพุต ฟังก์ชันการรวมจะส่งคืนค่าผลลัพธ์โดยการคำนวณค่าอินพุต
ปฏิบัติตามตัวอย่างการจัดการพนักงานที่ใช้ในบทก่อนหน้า ในที่นี้เราจะเข้าสู่คลาสบริการโดยใช้ฟังก์ชันสเกลาร์และฟังก์ชันรวมของ JPQL
ให้เราถือว่าตาราง jpadb.employee มีบันทึกต่อไปนี้
Eid | Ename | เงินเดือน | องศา |
---|---|---|---|
1201 | โกปาล | 40000 | ผู้จัดการฝ่ายเทคนิค |
1202 | มานิชา | 40000 | เครื่องอ่านหลักฐาน |
1203 | Masthanvali | 40000 | นักเขียนด้านเทคนิค |
1204 | Satish | 30000 | นักเขียนด้านเทคนิค |
1205 | กฤษณะ | 30000 | นักเขียนด้านเทคนิค |
1206 | Kiran | 35000 | เครื่องอ่านหลักฐาน |
สร้างคลาสชื่อ ScalarandAggregateFunctions.java ภายใต้ com.tutorialspoint.eclipselink.service แพคเกจดังนี้
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);
}
}
หลังจากคอมไพล์และเรียกใช้โปรแกรมข้างต้นแล้วคุณจะได้ผลลัพธ์ในแผงคอนโซลของ Eclipse IDE ดังนี้:
Employee NAME :GOPAL
Employee NAME :MANISHA
Employee NAME :MASTHANVALI
Employee NAME :SATISH
Employee NAME :KRISHNA
Employee NAME :KIRAN
ax Employee Salary :40000.0
ระหว่างและเช่นเดียวกับคำหลัก
"ระหว่าง" "และ" และ "ชอบ" เป็นคีย์เวิร์ดหลักของ JPQL คำหลักเหล่านี้ใช้หลัง Where clause ในแบบสอบถาม
สร้างคลาสชื่อ BetweenAndLikeFunctions.java ภายใต้ com.tutorialspoint.eclipselink.service แพคเกจดังนี้:
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( ));
}
}
}
หลังจากคอมไพล์และเรียกใช้โปรแกรมข้างต้นแล้วคุณจะได้ผลลัพธ์ในแผงคอนโซลของ Eclipse IDE ดังนี้:
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
การสั่งซื้อ
ในการสั่งซื้อระเบียนใน JPQL เราใช้คำสั่ง ORDER BY การใช้คำสั่งนี้เหมือนกับการใช้ใน SQL แต่เกี่ยวข้องกับเอนทิตี ทำตามคำสั่งตามตัวอย่าง
สร้างคลาส Ordering.java ภายใต้ com.tutorialspoint.eclipselink.service แพคเกจดังนี้:
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( ));
}
}
}
หลังจากคอมไพล์และเรียกใช้โปรแกรมข้างต้นแล้วคุณจะได้ผลลัพธ์ในแผงคอนโซลของ Eclipse IDE ดังนี้:
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
แบบสอบถามที่มีชื่อ
คำอธิบายประกอบ @NamedQuery ถูกกำหนดให้เป็นแบบสอบถามที่มีสตริงแบบสอบถามที่ไม่สามารถเปลี่ยนแปลงได้ที่กำหนดไว้ล่วงหน้า แทนที่จะใช้แบบสอบถามแบบไดนามิกการใช้แบบสอบถามที่ตั้งชื่ออาจช่วยปรับปรุงการจัดระเบียบรหัสโดยการแยกสตริงแบบสอบถาม JPQL ออกจาก POJO นอกจากนี้ยังส่งผ่านพารามิเตอร์การสืบค้นแทนที่จะฝังตัวอักษรแบบไดนามิกลงในสตริงการสืบค้นและส่งผลให้การสืบค้นมีประสิทธิภาพมากขึ้น
ก่อนอื่นให้เพิ่มคำอธิบายประกอบ @NamedQuery ในคลาสเอนทิตีพนักงานที่ชื่อ Employee.java ภายใต้ com.tutorialspoint.eclipselink.entity แพคเกจดังนี้:
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 + "]";
}
}
สร้างคลาสชื่อ NamedQueries.java ภายใต้ com.tutorialspoint.eclipselink.service แพคเกจดังนี้:
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( ));
}
}
}
หลังจากคอมไพล์และเรียกใช้โปรแกรมข้างต้นแล้วคุณจะได้ผลลัพธ์ในแผงคอนโซลของ Eclipse IDE ดังนี้:
Employee ID :1204 Employee Name :Satish
หลังจากเพิ่มคลาสข้างต้นทั้งหมดแล้วจะแสดงลำดับชั้นของแพ็กเกจดังนี้:
กระตือรือร้นและขี้เกียจโหลด
แนวคิดหลักของ JPA คือการสร้างสำเนาฐานข้อมูลซ้ำในหน่วยความจำแคช ในขณะที่ทำธุรกรรมกับฐานข้อมูลอันดับแรกจะมีผลกับข้อมูลที่ซ้ำกันและเฉพาะเมื่อมีการตกลงโดยใช้ตัวจัดการเอนทิตีการเปลี่ยนแปลงจะมีผลกับฐานข้อมูล
มีสองวิธีในการดึงข้อมูลจากฐานข้อมูล ได้แก่ การดึงข้อมูลอย่างกระตือรือร้นและการดึงข้อมูลแบบขี้เกียจ
ดึงข้อมูลอย่างกระตือรือร้น
ดึงข้อมูลทั้งหมดในขณะที่ค้นหาระเบียนโดยใช้คีย์หลัก
ขี้เกียจดึง
จะตรวจสอบความพร้อมใช้งานของการแจ้งเตือนด้วยคีย์หลักหากมีอยู่ หลังจากนั้นถ้าคุณเรียกเมธอด getter ใด ๆ ของเอนทิตีนั้นมันจะดึงข้อมูลทั้งหมด
แต่การดึงข้อมูลแบบขี้เกียจเป็นไปได้เมื่อคุณพยายามดึงข้อมูลบันทึกเป็นครั้งแรก ด้วยวิธีนี้สำเนาของระเบียนทั้งหมดจะถูกเก็บไว้ในหน่วยความจำแคชแล้ว ประสิทธิภาพที่ชาญฉลาดและขี้เกียจดึงเป็นที่นิยม