ไฮเบอร์เนต - คู่มือฉบับย่อ

JDBC คืออะไร?

JDBC ย่อมาจาก Java Database Connectivity. จัดเตรียมชุด Java API สำหรับเข้าถึงฐานข้อมูลเชิงสัมพันธ์จากโปรแกรม Java Java API เหล่านี้ช่วยให้โปรแกรม Java ดำเนินการคำสั่ง SQL และโต้ตอบกับฐานข้อมูลที่เข้ากันได้กับ SQL

JDBC จัดเตรียมสถาปัตยกรรมที่ยืดหยุ่นในการเขียนแอปพลิเคชันฐานข้อมูลที่เป็นอิสระซึ่งสามารถทำงานบนแพลตฟอร์มที่แตกต่างกันและโต้ตอบกับ DBMS ที่แตกต่างกันโดยไม่ต้องแก้ไขใด ๆ

ข้อดีข้อเสียของ JDBC

ข้อดีของ JDBC จุดด้อยของ JDBC

การประมวลผล SQL ที่สะอาดและเรียบง่าย

ประสิทธิภาพที่ดีพร้อมข้อมูลขนาดใหญ่

ดีมากสำหรับการใช้งานขนาดเล็ก

ไวยากรณ์ที่เรียบง่ายจึงเรียนรู้ได้ง่าย

ซับซ้อนหากใช้ในโครงการขนาดใหญ่

ค่าใช้จ่ายในการเขียนโปรแกรมขนาดใหญ่

ไม่มีการห่อหุ้ม

ยากที่จะใช้แนวคิด MVC

แบบสอบถามเป็น DBMS เฉพาะ

ทำไม Object Relational Mapping (ORM)?

เมื่อเราทำงานกับระบบเชิงวัตถุจะมีความไม่ตรงกันระหว่างโมเดลวัตถุและฐานข้อมูลเชิงสัมพันธ์ RDBMS แสดงข้อมูลในรูปแบบตารางในขณะที่ภาษาเชิงวัตถุเช่น Java หรือ C # แสดงเป็นกราฟของวัตถุที่เชื่อมต่อกัน

พิจารณา Java Class ต่อไปนี้พร้อมตัวสร้างที่เหมาะสมและฟังก์ชันสาธารณะที่เกี่ยวข้อง -

public class Employee {
   private int id;
   private String first_name; 
   private String last_name;   
   private int salary;  

   public Employee() {}
   public Employee(String fname, String lname, int salary) {
      this.first_name = fname;
      this.last_name = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public String getFirstName() {
      return first_name;
   }
   
   public String getLastName() {
      return last_name;
   }
   
   public int getSalary() {
      return salary;
   }
}

พิจารณาว่าวัตถุข้างต้นจะถูกจัดเก็บและเรียกดูในตาราง RDBMS ต่อไปนี้ -

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

ปัญหาแรกเกิดอะไรขึ้นถ้าเราต้องปรับเปลี่ยนการออกแบบฐานข้อมูลของเราหลังจากที่ได้พัฒนาหน้าหรือแอปพลิเคชันของเราไปแล้วไม่กี่หน้า ประการที่สองการโหลดและจัดเก็บวัตถุในฐานข้อมูลเชิงสัมพันธ์ทำให้เราพบปัญหาที่ไม่ตรงกันห้าประการต่อไปนี้ -

ซีเนียร์ ไม่ตรงกันและคำอธิบาย
1

Granularity

บางครั้งคุณจะมีโมเดลอ็อบเจ็กต์ซึ่งมีคลาสมากกว่าจำนวนตารางที่เกี่ยวข้องในฐานข้อมูล

2

Inheritance

RDBMS ไม่ได้กำหนดสิ่งที่คล้ายกับ Inheritance ซึ่งเป็นกระบวนทัศน์ธรรมชาติในภาษาโปรแกรมเชิงวัตถุ

3

Identity

RDBMS กำหนดแนวความคิดของ 'ความเหมือน' อย่างใดอย่างหนึ่งนั่นคือคีย์หลัก อย่างไรก็ตาม Java กำหนดทั้งเอกลักษณ์ของวัตถุ (a == b) และความเท่าเทียมกันของวัตถุ (a.equals (b))

4

Associations

ภาษาเชิงวัตถุแสดงถึงการเชื่อมโยงโดยใช้การอ้างอิงวัตถุในขณะที่ RDBMS แสดงถึงการเชื่อมโยงเป็นคอลัมน์คีย์ต่างประเทศ

5

Navigation

วิธีที่คุณเข้าถึงอ็อบเจ็กต์ใน Java และใน RDBMS นั้นแตกต่างกันโดยพื้นฐาน

Object-Rร่าเริง Mapping (ORM) เป็นวิธีการจัดการกับความไม่ตรงกันทั้งหมดข้างต้น

ORM คืออะไร?

ORM ย่อมาจาก Object-Rร่าเริง Mapping (ORM) เป็นเทคนิคการเขียนโปรแกรมสำหรับการแปลงข้อมูลระหว่างฐานข้อมูลเชิงสัมพันธ์กับภาษาโปรแกรมเชิงวัตถุเช่น Java, C # เป็นต้น

ระบบ ORM มีข้อดีเหนือ JDBC ธรรมดาดังต่อไปนี้ -

ซีเนียร์ ข้อดี
1 ให้รหัสธุรกิจเข้าถึงวัตถุแทนตาราง DB
2 ซ่อนรายละเอียดของการสืบค้น SQL จากตรรกะ OO
3 ขึ้นอยู่กับ JDBC 'ภายใต้ประทุน'
4 ไม่จำเป็นต้องจัดการกับการใช้งานฐานข้อมูล
5 เอนทิตีตามแนวคิดทางธุรกิจมากกว่าโครงสร้างฐานข้อมูล
6 การจัดการธุรกรรมและการสร้างคีย์อัตโนมัติ
7 การพัฒนาแอปพลิเคชันอย่างรวดเร็ว

โซลูชัน ORM ประกอบด้วยสี่เอนทิตีต่อไปนี้ -

ซีเนียร์ แนวทางแก้ไข
1 API เพื่อดำเนินการ CRUD พื้นฐานกับอ็อบเจ็กต์ของคลาสถาวร
2 ภาษาหรือ API เพื่อระบุคิวรีที่อ้างถึงคลาสและคุณสมบัติของคลาส
3 สิ่งอำนวยความสะดวกที่กำหนดค่าได้สำหรับการระบุข้อมูลเมตาของการทำแผนที่
4 เทคนิคในการโต้ตอบกับอ็อบเจ็กต์ธุรกรรมเพื่อทำการตรวจสอบสกปรกการเชื่อมโยงแบบขี้เกียจดึงข้อมูลและฟังก์ชันการเพิ่มประสิทธิภาพอื่น ๆ

Java ORM Frameworks

มีเฟรมเวิร์กถาวรและอ็อพชัน ORM หลายตัวใน Java เฟรมเวิร์กถาวรคือบริการ ORM ที่จัดเก็บและดึงอ็อบเจ็กต์ไปยังฐานข้อมูลเชิงสัมพันธ์

  • Enterprise JavaBeans Entity Beans
  • Java Data Objects
  • Castor
  • TopLink
  • สปริง DAO
  • Hibernate
  • และอื่น ๆ อีกมากมาย

ไฮเบอร์เนตคือไฟล์ Object-Rร่าเริง Mแอป (ORM) โซลูชันสำหรับ JAVA เป็นเฟรมเวิร์กถาวรแบบโอเพนซอร์สที่สร้างโดย Gavin King ในปี 2544 เป็นบริการ Object-Relational Persistence และ Query ที่มีประสิทธิภาพสูงสำหรับแอปพลิเคชัน Java ใด ๆ

ไฮเบอร์เนตแมปคลาส Java กับตารางฐานข้อมูลและจากชนิดข้อมูล Java ไปยังชนิดข้อมูล SQL และช่วยให้นักพัฒนาจาก 95% ของงานเขียนโปรแกรมที่เกี่ยวข้องกับการคงอยู่ของข้อมูลทั่วไป

ไฮเบอร์เนตอยู่ระหว่างอ็อบเจ็กต์ Java แบบดั้งเดิมและเซิร์ฟเวอร์ฐานข้อมูลเพื่อจัดการงานทั้งหมดในการคงอยู่ของอ็อบเจ็กต์เหล่านั้นตามกลไกและรูปแบบ O / R ที่เหมาะสม

ข้อดีของไฮเบอร์เนต

  • Hibernate ดูแลการแมปคลาส Java กับตารางฐานข้อมูลโดยใช้ไฟล์ XML และไม่ต้องเขียนโค้ดใด ๆ

  • จัดเตรียม API แบบง่ายสำหรับการจัดเก็บและการดึงอ็อบเจ็กต์ Java เข้าและออกจากฐานข้อมูลโดยตรง

  • หากมีการเปลี่ยนแปลงในฐานข้อมูลหรือในตารางใด ๆ คุณต้องเปลี่ยนคุณสมบัติไฟล์ XML เท่านั้น

  • แยกประเภท SQL ที่ไม่คุ้นเคยออกไปและให้วิธีการแก้ไข Java Objects ที่คุ้นเคย

  • ไฮเบอร์เนตไม่จำเป็นต้องมีแอปพลิเคชันเซิร์ฟเวอร์ในการทำงาน

  • จัดการการเชื่อมโยงที่ซับซ้อนของวัตถุในฐานข้อมูลของคุณ

  • ลดการเข้าถึงฐานข้อมูลด้วยกลยุทธ์การดึงข้อมูลอัจฉริยะ

  • ให้การสืบค้นข้อมูลอย่างง่าย

ฐานข้อมูลที่รองรับ

Hibernate รองรับ RDBMS หลักเกือบทั้งหมด ต่อไปนี้เป็นรายการเอ็นจิ้นฐานข้อมูลบางส่วนที่ Hibernate รองรับ -

  • เครื่องมือฐานข้อมูล HSQL
  • DB2/NT
  • MySQL
  • PostgreSQL
  • FrontBase
  • Oracle
  • ฐานข้อมูล Microsoft SQL Server
  • Sybase SQL Server
  • Informix Dynamic Server

เทคโนโลยีที่รองรับ

Hibernate รองรับเทคโนโลยีอื่น ๆ ที่หลากหลาย ได้แก่ -

  • XDoclet Spring
  • J2EE
  • ปลั๊กอิน Eclipse
  • Maven

Hibernate มีสถาปัตยกรรมแบบเลเยอร์ซึ่งช่วยให้ผู้ใช้สามารถดำเนินการได้โดยไม่ต้องรู้จัก API ที่อยู่เบื้องหลัง ไฮเบอร์เนตใช้ประโยชน์จากฐานข้อมูลและข้อมูลการกำหนดค่าเพื่อให้บริการการคงอยู่ (และวัตถุถาวร) แก่แอปพลิเคชัน

ต่อไปนี้เป็นมุมมองระดับสูงของ Hibernate Application Architecture

ต่อไปนี้เป็นมุมมองโดยละเอียดของ Hibernate Application Architecture พร้อมคลาสหลักที่สำคัญ

Hibernate ใช้ Java API ที่มีอยู่ต่างๆเช่น JDBC, Java Transaction API (JTA) และ Java Naming and Directory Interface (JNDI) JDBC จัดเตรียมระดับพื้นฐานของการทำงานที่เป็นนามธรรมร่วมกับฐานข้อมูลเชิงสัมพันธ์ซึ่งช่วยให้ฐานข้อมูลเกือบทั้งหมดที่มีไดรเวอร์ JDBC รองรับโดย Hibernate JNDI และ JTA อนุญาตให้ Hibernate รวมเข้ากับแอปพลิเคชันเซิร์ฟเวอร์ J2EE

ส่วนต่อไปนี้ให้คำอธิบายสั้น ๆ ของแต่ละคลาสที่เกี่ยวข้องกับ Hibernate Application Architecture

วัตถุการกำหนดค่า

ออบเจ็กต์ Configuration เป็นอ็อบเจ็กต์ Hibernate แรกที่คุณสร้างในแอปพลิเคชัน Hibernate โดยปกติจะสร้างเพียงครั้งเดียวในระหว่างการเริ่มต้นแอปพลิเคชัน มันแสดงถึงไฟล์คอนฟิกูเรชันหรือคุณสมบัติที่ Hibernate ต้องการ

วัตถุ Configuration มีส่วนประกอบสองคีย์ -

  • Database Connection- จัดการผ่านไฟล์กำหนดค่าอย่างน้อยหนึ่งไฟล์ที่ Hibernate รองรับ ไฟล์เหล่านี้คือhibernate.properties และ hibernate.cfg.xml.

  • Class Mapping Setup - องค์ประกอบนี้สร้างการเชื่อมต่อระหว่างคลาส Java และตารางฐานข้อมูล

วัตถุ SessionFactory

คอนฟิกูเรชันอ็อบเจ็กต์ถูกใช้เพื่อสร้างอ็อบเจ็กต์ SessionFactory ซึ่งจะกำหนดค่า Hibernate สำหรับแอ็พพลิเคชันโดยใช้ไฟล์คอนฟิกูเรชันที่ให้มาและอนุญาตให้อ็อบเจ็กต์ Session ถูกสร้างอินสแตนซ์ SessionFactory เป็นอ็อบเจ็กต์ที่ปลอดภัยของเธรดและใช้โดยเธรดทั้งหมดของแอ็พพลิเคชัน

SessionFactory เป็นวัตถุที่มีน้ำหนักมาก โดยปกติจะสร้างขึ้นระหว่างการเริ่มต้นแอปพลิเคชันและเก็บไว้เพื่อใช้ในภายหลัง คุณจะต้องมีวัตถุ SessionFactory หนึ่งรายการต่อฐานข้อมูลโดยใช้ไฟล์กำหนดค่าแยกต่างหาก ดังนั้นหากคุณใช้หลายฐานข้อมูลคุณจะต้องสร้างวัตถุ SessionFactory หลายรายการ

วัตถุเซสชัน

เซสชันใช้เพื่อรับการเชื่อมต่อทางกายภาพกับฐานข้อมูล วัตถุเซสชันมีน้ำหนักเบาและออกแบบมาเพื่อสร้างอินสแตนซ์ทุกครั้งที่จำเป็นต้องมีการโต้ตอบกับฐานข้อมูล วัตถุถาวรจะถูกบันทึกและเรียกค้นผ่านวัตถุเซสชัน

ไม่ควรเปิดวัตถุเซสชันไว้เป็นเวลานานเนื่องจากโดยปกติแล้ววัตถุเหล่านี้จะไม่ปลอดภัยสำหรับเธรดและควรสร้างและทำลายวัตถุเหล่านั้นตามความจำเป็น

วัตถุธุรกรรม

ธุรกรรมแสดงถึงหน่วยการทำงานกับฐานข้อมูลและ RDBMS ส่วนใหญ่รองรับฟังก์ชันการทำงานของธุรกรรม ธุรกรรมใน Hibernate ได้รับการจัดการโดยตัวจัดการธุรกรรมและธุรกรรม (จาก JDBC หรือ JTA)

นี่เป็นอ็อบเจ็กต์ที่เป็นทางเลือกและแอปพลิเคชันไฮเบอร์เนตอาจเลือกที่จะไม่ใช้อินเทอร์เฟซนี้แทนการจัดการธุรกรรมในรหัสแอปพลิเคชันของตนเอง

วัตถุแบบสอบถาม

อ็อบเจ็กต์เคียวรีใช้สตริง SQL หรือ Hibernate Query Language (HQL) เพื่อดึงข้อมูลจากฐานข้อมูลและสร้างอ็อบเจ็กต์ อินสแตนซ์แบบสอบถามใช้เพื่อผูกพารามิเตอร์การสืบค้น จำกัด จำนวนผลลัพธ์ที่ส่งกลับโดยคิวรีและในที่สุดก็ดำเนินการค้นหา

วัตถุเกณฑ์

อ็อบเจ็กต์เกณฑ์ถูกใช้เพื่อสร้างและรันเคียวรีเกณฑ์เชิงอ็อบเจ็กต์เพื่อดึงอ็อบเจ็กต์

บทนี้อธิบายวิธีการติดตั้ง Hibernate และแพ็กเกจอื่น ๆ ที่เกี่ยวข้องเพื่อเตรียมสภาพแวดล้อมสำหรับแอปพลิเคชัน Hibernate เราจะทำงานกับฐานข้อมูล MySQL เพื่อทดลองกับตัวอย่าง Hibernate ดังนั้นตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าฐานข้อมูล MySQL แล้ว สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ MySQL, คุณสามารถตรวจสอบของเราสอน MySQL

กำลังดาวน์โหลด Hibernate

สันนิษฐานว่าคุณได้ติดตั้ง Java เวอร์ชันล่าสุดในระบบของคุณแล้ว ต่อไปนี้เป็นขั้นตอนง่ายๆในการดาวน์โหลดและติดตั้งไฮเบอร์เนตบนระบบของคุณ -

  • เลือกว่าคุณต้องการติดตั้ง Hibernate บน Windows หรือ Unix จากนั้นดำเนินการขั้นตอนต่อไปเพื่อดาวน์โหลดไฟล์. zip สำหรับ windows และไฟล์. tz สำหรับ Unix

  • ดาวน์โหลด Hibernate เวอร์ชันล่าสุดจาก http://www.hibernate.org/downloads.

  • ในขณะที่เขียนบทช่วยสอนนี้ฉันดาวน์โหลด hibernate-distribution3.6.4.Final และเมื่อคุณแตกไฟล์ที่ดาวน์โหลดมาไฟล์นั้นจะให้โครงสร้างไดเร็กทอรีดังที่แสดงในภาพต่อไปนี้

การติดตั้งไฮเบอร์เนต

เมื่อคุณดาวน์โหลดและคลายซิปไฟล์ Hibernate Installation เวอร์ชันล่าสุดแล้วคุณต้องทำตามสองขั้นตอนง่ายๆดังต่อไปนี้ ตรวจสอบให้แน่ใจว่าคุณตั้งค่าตัวแปร CLASSPATH ของคุณอย่างถูกต้องมิฉะนั้นคุณจะประสบปัญหาในขณะที่รวบรวมแอปพลิเคชันของคุณ

  • ตอนนี้คัดลอกไฟล์ไลบรารีทั้งหมดจาก /lib ลงใน CLASSPATH ของคุณและเปลี่ยนตัวแปร classpath ของคุณเพื่อรวม JAR ทั้งหมด -

  • สุดท้ายคัดลอก hibernate3.jarไฟล์ลงใน CLASSPATH ของคุณ ไฟล์นี้อยู่ในไดเร็กทอรีรากของการติดตั้งและเป็น JAR หลักที่ Hibernate ต้องใช้ในการทำงาน

ข้อกำหนดเบื้องต้นของไฮเบอร์เนต

ต่อไปนี้เป็นรายการแพ็คเกจ / ไลบรารีที่ Hibernate ต้องการและคุณควรติดตั้งก่อนเริ่มด้วย Hibernate ในการติดตั้งแพ็คเกจเหล่านี้คุณจะต้องคัดลอกไฟล์ไลบรารีจาก/lib ลงใน CLASSPATH ของคุณและเปลี่ยนตัวแปร CLASSPATH ของคุณตามนั้น

ซีเนียร์ แพ็คเกจ / ไลบรารี
1

dom4j

การแยกวิเคราะห์ XML www.dom4j.org/

2

Xalan

โปรเซสเซอร์ XSLT https://xml.apache.org/xalan-j/

3

Xerces

Xerces Java Parser https://xml.apache.org/xerces-j/

4

cglib

การเปลี่ยนแปลงที่เหมาะสมกับคลาส Java ที่รันไทม์ http://cglib.sourceforge.net/

5

log4j

การบันทึก Faremwork https://logging.apache.org/log4j

6

Commons

การบันทึกอีเมล ฯลฯ https://jakarta.apache.org/commons

7

SLF4J

Logging Facade สำหรับ Java https://www.slf4j.org

ไฮเบอร์เนตจำเป็นต้องทราบล่วงหน้า - จะค้นหาข้อมูลการแมปที่กำหนดว่าคลาส Java ของคุณเกี่ยวข้องกับตารางฐานข้อมูลอย่างไร ไฮเบอร์เนตยังต้องการชุดการตั้งค่าคอนฟิกที่เกี่ยวข้องกับฐานข้อมูลและพารามิเตอร์อื่น ๆ ที่เกี่ยวข้อง ข้อมูลดังกล่าวทั้งหมดมักจัดให้เป็นไฟล์คุณสมบัติ Java มาตรฐานที่เรียกว่าhibernate.propertiesหรือเป็นไฟล์ XML ชื่อ hibernate.cfg.xml.

ฉันจะพิจารณาไฟล์ที่จัดรูปแบบ XML hibernate.cfg.xmlเพื่อระบุคุณสมบัติไฮเบอร์เนตที่จำเป็นในตัวอย่างของฉัน คุณสมบัติส่วนใหญ่ใช้ค่าดีฟอลต์และไม่จำเป็นต้องระบุไว้ในไฟล์คุณสมบัติเว้นแต่ว่าจำเป็นจริงๆ ไฟล์นี้ถูกเก็บไว้ในไดเร็กทอรีรากของคลาสพา ธ ของแอปพลิเคชันของคุณ

คุณสมบัติไฮเบอร์เนต

ต่อไปนี้เป็นรายการคุณสมบัติที่สำคัญคุณจะต้องกำหนดค่าสำหรับฐานข้อมูลในสถานการณ์แบบสแตนด์อโลน -

ซีเนียร์ คุณสมบัติและคำอธิบาย
1

hibernate.dialect

คุณสมบัตินี้ทำให้ Hibernate สร้าง SQL ที่เหมาะสมสำหรับฐานข้อมูลที่เลือก

2

hibernate.connection.driver_class

คลาสไดรเวอร์ JDBC

3

hibernate.connection.url

JDBC URL ไปยังอินสแตนซ์ฐานข้อมูล

4

hibernate.connection.username

ชื่อผู้ใช้ฐานข้อมูล

5

hibernate.connection.password

รหัสผ่านฐานข้อมูล

6

hibernate.connection.pool_size

จำกัด จำนวนการเชื่อมต่อที่รออยู่ในกลุ่มการเชื่อมต่อฐานข้อมูลไฮเบอร์เนต

7

hibernate.connection.autocommit

อนุญาตให้ใช้โหมด autocommit สำหรับการเชื่อมต่อ JDBC

หากคุณใช้ฐานข้อมูลร่วมกับแอ็พพลิเคชันเซิร์ฟเวอร์และ JNDI คุณจะต้องกำหนดค่าคุณสมบัติต่อไปนี้ -

ซีเนียร์ คุณสมบัติและคำอธิบาย
1

hibernate.connection.datasource

ชื่อ JNDI ที่กำหนดในบริบทแอ็พพลิเคชันเซิร์ฟเวอร์ซึ่งคุณกำลังใช้สำหรับแอ็พพลิเคชัน

2

hibernate.jndi.class

คลาส InitialContext สำหรับ JNDI

3

hibernate.jndi.<JNDIpropertyname>

ผ่านคุณสมบัติ JNDI ใด ๆ ที่คุณชอบไป JNDI InitialContext

4

hibernate.jndi.url

จัดเตรียม URL สำหรับ JNDI

5

hibernate.connection.username

ชื่อผู้ใช้ฐานข้อมูล

6

hibernate.connection.password

รหัสผ่านฐานข้อมูล

ไฮเบอร์เนตด้วยฐานข้อมูล MySQL

MySQL เป็นระบบฐานข้อมูลโอเพนซอร์สที่ได้รับความนิยมมากที่สุดระบบหนึ่งในปัจจุบัน ให้เราสร้างhibernate.cfg.xmlไฟล์การกำหนดค่าและวางไว้ในรูทของคลาสพา ธ ของแอปพลิเคชันของคุณ คุณจะต้องแน่ใจว่าคุณมีtestdb ฐานข้อมูลที่มีอยู่ในฐานข้อมูล MySQL ของคุณและคุณมีผู้ใช้ test สามารถเข้าถึงฐานข้อมูลได้

ไฟล์คอนฟิกูเรชัน XML ต้องเป็นไปตาม Hibernate 3 Configuration DTD ซึ่งมีอยู่ที่ http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
      
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>
      
      <!-- Assume test is the database name -->
      
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
      
      <property name = "hibernate.connection.username">
         root
      </property>
      
      <property name = "hibernate.connection.password">
         root123
      </property>
      
      <!-- List of XML mapping files -->
      <mapping resource = "Employee.hbm.xml"/>
      
   </session-factory>
</hibernate-configuration>

ไฟล์การกำหนดค่าข้างต้นประกอบด้วย <mapping> แท็กซึ่งเกี่ยวข้องกับไฟล์ hibernatemapping และเราจะเห็นในบทถัดไปว่าไฟล์การแมปไฮเบอร์เนตคืออะไรและเราใช้มันอย่างไรและทำไม?

ต่อไปนี้เป็นรายการประเภทคุณสมบัติของฐานข้อมูลที่สำคัญต่างๆ -

ซีเนียร์ ฐานข้อมูลและภาษาถิ่น
1

DB2

org.hibernate.dialect.DB2Dialect

2

HSQLDB

org.hibernate.dialect.HSQLDialect

3

HypersonicSQL

org.hibernate.dialect.HSQLDialect

4

Informix

org.hibernate.dialect.InformixDialect

5

Ingres

org.hibernate.dialect.IngresDialect

6

Interbase

org.hibernate.dialect.InterbaseDialect

7

Microsoft SQL Server 2000

org.hibernate.dialect.SQLServerDialect

8

Microsoft SQL Server 2005

org.hibernate.dialect.SQLServer2005Dialect

9

Microsoft SQL Server 2008

org.hibernate.dialect.SQLServer2008Dialect

10

MySQL

org.hibernate.dialect.MySQLDialect

11

Oracle (any version)

org.hibernate.dialect.OracleDialect

12

Oracle 11g

org.hibernate.dialect.Oracle10gDialect

13

Oracle 10g

org.hibernate.dialect.Oracle10gDialect

14

Oracle 9i

org.hibernate.dialect.Oracle9iDialect

15

PostgreSQL

org.hibernate.dialect.PostgreSQLDialect

16

Progress

org.hibernate.dialect.ProgressDialect

17

SAP DB

org.hibernate.dialect.SAPDBDialect

18

Sybase

org.hibernate.dialect.SybaseDialect

19

Sybase Anywhere

org.hibernate.dialect.SybaseAnywhereDialect

เซสชันใช้เพื่อรับการเชื่อมต่อทางกายภาพกับฐานข้อมูล วัตถุเซสชันมีน้ำหนักเบาและออกแบบมาเพื่อสร้างอินสแตนซ์ทุกครั้งที่จำเป็นต้องมีการโต้ตอบกับฐานข้อมูล วัตถุถาวรจะถูกบันทึกและเรียกค้นผ่านวัตถุเซสชัน

ไม่ควรเปิดวัตถุเซสชันไว้เป็นเวลานานเนื่องจากโดยปกติแล้ววัตถุเหล่านี้จะไม่ปลอดภัยสำหรับเธรดและควรสร้างและทำลายวัตถุเหล่านั้นตามความจำเป็น หน้าที่หลักของเซสชันคือการเสนอสร้างอ่านและลบการดำเนินการสำหรับอินสแตนซ์ของคลาสเอนทิตีที่แมป

อินสแตนซ์อาจมีอยู่ในหนึ่งในสามสถานะต่อไปนี้ในช่วงเวลาที่กำหนด -

  • transient - อินสแตนซ์ใหม่ของคลาสถาวรซึ่งไม่เกี่ยวข้องกับเซสชันและไม่มีการนำเสนอในฐานข้อมูลและไม่มีการพิจารณาค่าตัวระบุชั่วคราวโดยไฮเบอร์เนต

  • persistent- คุณสามารถทำให้อินสแตนซ์ชั่วคราวคงอยู่ได้โดยเชื่อมโยงกับเซสชัน อินสแตนซ์ถาวรมีการแสดงในฐานข้อมูลค่าตัวระบุและเชื่อมโยงกับเซสชัน

  • detached - เมื่อเราปิด Hibernate Session อินสแตนซ์ถาวรจะกลายเป็นอินสแตนซ์แยก

อินสแตนซ์เซสชันสามารถต่ออนุกรมได้หากคลาสแบบต่อเนื่องสามารถต่ออนุกรมกันได้ ธุรกรรมทั่วไปควรใช้สำนวนต่อไปนี้ -

Session session = factory.openSession();
Transaction tx = null;

try {
   tx = session.beginTransaction();
   // do some work
   ...
   tx.commit();
}

catch (Exception e) {
   if (tx!=null) tx.rollback();
   e.printStackTrace(); 
} finally {
   session.close();
}

หากเซสชันมีข้อยกเว้นธุรกรรมจะต้องย้อนกลับและเซสชันจะต้องถูกยกเลิก

วิธีการเชื่อมต่อเซสชัน

มีหลายวิธีที่จัดทำโดย Sessionอินเทอร์เฟซ แต่ฉันจะแสดงรายการวิธีการที่สำคัญบางอย่างเท่านั้นซึ่งเราจะใช้ในบทช่วยสอนนี้ คุณสามารถตรวจสอบเอกสารไฮเบอร์เนตเพื่อดูรายการวิธีการทั้งหมดที่เกี่ยวข้องSession และ SessionFactory.

ซีเนียร์ วิธีการและคำอธิบายเซสชัน
1

Transaction beginTransaction()

เริ่มต้นหน่วยของการทำงานและส่งคืนอ็อบเจ็กต์ธุรกรรมที่เกี่ยวข้อง

2

void cancelQuery()

ยกเลิกการดำเนินการของแบบสอบถามปัจจุบัน

3

void clear()

ล้างเซสชันโดยสมบูรณ์

4

Connection close()

สิ้นสุดเซสชันโดยปล่อยการเชื่อมต่อ JDBC และล้างข้อมูล

5

Criteria createCriteria(Class persistentClass)

สร้างอินสแตนซ์เกณฑ์ใหม่สำหรับคลาสเอนทิตีที่กำหนดหรือซูเปอร์คลาสของคลาสเอนทิตี

6

Criteria createCriteria(String entityName)

สร้างอินสแตนซ์เกณฑ์ใหม่สำหรับชื่อเอนทิตีที่กำหนด

7

Serializable getIdentifier(Object object)

ส่งคืนค่าตัวระบุของเอนทิตีที่กำหนดซึ่งเชื่อมโยงกับเซสชันนี้

8

Query createFilter(Object collection, String queryString)

สร้างอินสแตนซ์ใหม่ของแบบสอบถามสำหรับคอลเล็กชันและสตริงตัวกรองที่กำหนด

9

Query createQuery(String queryString)

สร้างอินสแตนซ์ใหม่ของแบบสอบถามสำหรับสตริงแบบสอบถาม HQL ที่กำหนด

10

SQLQuery createSQLQuery(String queryString)

สร้างอินสแตนซ์ใหม่ของ SQLQuery สำหรับสตริงแบบสอบถาม SQL ที่กำหนด

11

void delete(Object object)

ลบอินสแตนซ์ถาวรออกจากที่เก็บข้อมูล

12

void delete(String entityName, Object object)

ลบอินสแตนซ์ถาวรออกจากที่เก็บข้อมูล

13

Session get(String entityName, Serializable id)

ส่งคืนอินสแตนซ์ถาวรของเอนทิตีที่ระบุด้วยตัวระบุที่กำหนดหรือค่าว่างหากไม่มีอินสแตนซ์ถาวรดังกล่าว

14

SessionFactory getSessionFactory()

รับโรงงานเซสชันที่สร้างเซสชันนี้

15

void refresh(Object object)

อ่านสถานะของอินสแตนซ์ที่กำหนดอีกครั้งจากฐานข้อมูลพื้นฐาน

16

Transaction getTransaction()

รับอินสแตนซ์ธุรกรรมที่เชื่อมโยงกับเซสชันนี้

17

boolean isConnected()

ตรวจสอบว่าเซสชันเชื่อมต่ออยู่หรือไม่

18

boolean isDirty()

เซสชันนี้มีการเปลี่ยนแปลงใด ๆ ที่ต้องซิงโครไนซ์กับฐานข้อมูลหรือไม่

19

boolean isOpen()

ตรวจสอบว่าเซสชันยังเปิดอยู่หรือไม่

20

Serializable save(Object object)

คงอยู่ในอินสแตนซ์ชั่วคราวที่กำหนดก่อนกำหนดตัวระบุที่สร้างขึ้น

21

void saveOrUpdate(Object object)

บันทึก (Object) หรืออัปเดต (Object) อินสแตนซ์ที่กำหนด

22

void update(Object object)

อัปเดตอินสแตนซ์ถาวรด้วยตัวระบุของอินสแตนซ์แยกที่กำหนด

23

void update(String entityName, Object object)

อัปเดตอินสแตนซ์ถาวรด้วยตัวระบุของอินสแตนซ์แยกที่กำหนด

แนวคิดทั้งหมดของ Hibernate คือการนำค่าจากแอตทริบิวต์คลาส Java และคงไว้ที่ตารางฐานข้อมูล เอกสารการแมปช่วยไฮเบอร์เนตในการกำหนดวิธีดึงค่าจากคลาสและแมปกับตารางและฟิลด์ที่เกี่ยวข้อง

คลาส Java ที่อ็อบเจ็กต์หรืออินสแตนซ์จะถูกเก็บไว้ในตารางฐานข้อมูลเรียกว่าคลาสถาวรในไฮเบอร์เนต ไฮเบอร์เนตจะทำงานได้ดีที่สุดหากคลาสเหล่านี้ปฏิบัติตามกฎง่ายๆหรือที่เรียกว่าPlain Old Java Object (POJO) แบบจำลองการเขียนโปรแกรม

กฎหลักของคลาสถาวรมีดังต่อไปนี้อย่างไรก็ตามไม่มีกฎใดที่เป็นข้อกำหนดที่ยาก -

  • คลาส Java ทั้งหมดที่จะคงอยู่จำเป็นต้องมีตัวสร้างเริ่มต้น

  • คลาสทั้งหมดควรมี ID เพื่อให้สามารถระบุอ็อบเจ็กต์ของคุณภายใน Hibernate และฐานข้อมูลได้ง่าย คุณสมบัตินี้แมปกับคอลัมน์คีย์หลักของตารางฐานข้อมูล

  • แอตทริบิวต์ทั้งหมดที่จะคงอยู่ควรประกาศเป็นส่วนตัวและมี getXXX และ setXXX วิธีการที่กำหนดในสไตล์ JavaBean

  • คุณลักษณะหลักของไฮเบอร์เนตพร็อกซีขึ้นอยู่กับคลาสที่คงอยู่ว่าไม่ใช่ขั้นสุดท้ายหรือการใช้งานอินเทอร์เฟซที่ประกาศวิธีการสาธารณะทั้งหมด

  • คลาสทั้งหมดที่ไม่ขยายหรือใช้คลาสพิเศษและอินเทอร์เฟซที่จำเป็นโดยเฟรมเวิร์ก EJB

ชื่อ POJO ใช้เพื่อเน้นว่าอ็อบเจ็กต์ที่กำหนดเป็น Java Object ธรรมดาไม่ใช่อ็อบเจ็กต์พิเศษและโดยเฉพาะอย่างยิ่งไม่ใช่ Enterprise JavaBean

ตัวอย่าง POJO อย่างง่าย

จากกฎสองสามข้อที่กล่าวมาข้างต้นเราสามารถกำหนดคลาส POJO ได้ดังนี้ -

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

การแม็พวัตถุ / เชิงสัมพันธ์มักจะกำหนดไว้ในเอกสาร XML ไฟล์การแมปนี้สั่งให้ไฮเบอร์เนต - จะแม็พคลาสหรือคลาสที่กำหนดกับตารางฐานข้อมูลได้อย่างไร

แม้ว่าผู้ใช้ Hibernate หลายคนจะเลือกที่จะเขียน XML ด้วยมือ แต่ก็มีเครื่องมือมากมายในการสร้างเอกสารการแมป ซึ่งรวมถึงXDoclet, Middlegen และ AndroMDA สำหรับผู้ใช้ไฮเบอร์เนตขั้นสูง

ให้เราพิจารณาคลาส POJO ที่กำหนดไว้ก่อนหน้าซึ่งวัตถุจะยังคงอยู่ในตารางที่กำหนดไว้ในส่วนถัดไป

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

จะมีตารางหนึ่งตารางที่สอดคล้องกับวัตถุแต่ละชิ้นที่คุณยินดีให้การคงอยู่ พิจารณาวัตถุข้างต้นจำเป็นต้องจัดเก็บและเรียกคืนในตาราง RDBMS ต่อไปนี้ -

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

จากสองเอนทิตีข้างต้นเราสามารถกำหนดไฟล์การแม็ปต่อไปนี้ซึ่งจะสั่งให้ไฮเบอร์เนตวิธีการแมปคลาสหรือคลาสที่กำหนดกับตารางฐานข้อมูล

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

คุณควรบันทึกเอกสารการแมปในไฟล์ที่มีรูปแบบ <classname> .hbm.xml เราบันทึกเอกสารการทำแผนที่ไว้ในไฟล์ Employee.hbm.xml

ให้เราเข้าใจรายละเอียดเล็กน้อยเกี่ยวกับองค์ประกอบการแมปที่ใช้ในไฟล์การแมป -

  • เอกสารการแมปเป็นเอกสาร XML ที่มี <hibernate-mapping> เป็นองค์ประกอบรากซึ่งมีไฟล์ <class> องค์ประกอบ

  • <class>อิลิเมนต์ถูกใช้เพื่อกำหนดการแม็พเฉพาะจากคลาส Java ไปยังตารางฐานข้อมูล ชื่อคลาส Java ถูกระบุโดยใช้name แอตทริบิวต์ขององค์ประกอบคลาสและฐานข้อมูล table ระบุชื่อโดยใช้แอตทริบิวต์ table

  • <meta> องค์ประกอบเป็นองค์ประกอบทางเลือกและสามารถใช้เพื่อสร้างคำอธิบายชั้นเรียน

  • <id>องค์ประกอบแมปแอตทริบิวต์ ID เฉพาะในคลาสกับคีย์หลักของตารางฐานข้อมูล name แอตทริบิวต์ขององค์ประกอบ id หมายถึงคุณสมบัติในคลาสและ columnแอตทริบิวต์หมายถึงคอลัมน์ในตารางฐานข้อมูล type แอตทริบิวต์มีประเภทการแมปไฮเบอร์เนตประเภทการแมปนี้จะแปลงจาก Java เป็นชนิดข้อมูล SQL

  • <generator>องค์ประกอบภายในองค์ประกอบ id ถูกใช้เพื่อสร้างค่าคีย์หลักโดยอัตโนมัติ class แอตทริบิวต์ขององค์ประกอบตัวสร้างถูกตั้งค่าเป็น native เพื่อให้จำศีลได้ identity, sequence, หรือ hilo อัลกอริทึมในการสร้างคีย์หลักขึ้นอยู่กับความสามารถของฐานข้อมูลพื้นฐาน

  • <property>องค์ประกอบใช้เพื่อแม็พคุณสมบัติคลาส Java กับคอลัมน์ในตารางฐานข้อมูล name แอตทริบิวต์ขององค์ประกอบหมายถึงคุณสมบัติในคลาสและ columnแอตทริบิวต์หมายถึงคอลัมน์ในตารางฐานข้อมูล type แอตทริบิวต์มีประเภทการแมปไฮเบอร์เนตประเภทการแมปนี้จะแปลงจาก Java เป็นชนิดข้อมูล SQL

มีแอตทริบิวต์และองค์ประกอบอื่น ๆ ที่พร้อมใช้งานซึ่งจะใช้ในเอกสารการทำแผนที่และฉันจะพยายามครอบคลุมให้มากที่สุดในขณะที่พูดคุยเกี่ยวกับหัวข้ออื่น ๆ ที่เกี่ยวข้องกับไฮเบอร์เนต

เมื่อคุณเตรียมเอกสารการแมปไฮเบอร์เนตคุณจะพบว่าคุณแมปชนิดข้อมูล Java กับชนิดข้อมูล RDBMS typesประกาศและใช้ในไฟล์การแมปไม่ใช่ชนิดข้อมูล Java ไม่ใช่ประเภทฐานข้อมูล SQL เช่นกัน ประเภทนี้เรียกว่าHibernate mapping typesซึ่งสามารถแปลจาก Java เป็นชนิดข้อมูล SQL และในทางกลับกัน

บทนี้แสดงรายการพื้นฐานวันที่และเวลาวัตถุขนาดใหญ่และประเภทการทำแผนที่ในตัวอื่น ๆ ทั้งหมด

ประเภทดั้งเดิม

ประเภทการทำแผนที่ ประเภท Java ประเภท ANSI SQL
จำนวนเต็ม int หรือ java.lang.Integer จำนวนเต็ม
ยาว ยาวหรือ java.lang.Long ใหญ่
สั้น สั้นหรือ java.lang.Short SMALLINT
ลอย ลอยหรือ java.lang.Float ลอย
สองเท่า double หรือ java.lang.Double สองเท่า
big_decimal java.math.BigDecimal NUMERIC
ตัวละคร java.lang.String ชาร์ (1)
สตริง java.lang.String VARCHAR
ไบต์ ไบต์หรือ java.lang Byte TINYINT
บูลีน บูลีนหรือ java.lang.Boolean นิดหน่อย
ใช่ไม่ใช่ บูลีนหรือ java.lang.Boolean CHAR (1) ('Y' หรือ 'N')
ถูกผิด บูลีนหรือ java.lang.Boolean CHAR (1) ('T' หรือ 'F')

ประเภทวันที่และเวลา

ประเภทการทำแผนที่ ประเภท Java ประเภท ANSI SQL
วันที่ java.util.Date หรือ java.sql.Date วันที่
เวลา java.util.Date หรือ java.sql.Time เวลา
การประทับเวลา java.util.Date หรือ java.sql.Timestamp TIMESTAMP
ปฏิทิน java.util.Calendar TIMESTAMP
calendar_date java.util.Calendar วันที่

ประเภทวัตถุไบนารีและขนาดใหญ่

ประเภทการทำแผนที่ ประเภท Java ประเภท ANSI SQL
ไบนารี่ ไบต์ [] VARBINARY (หรือ BLOB)
ข้อความ java.lang.String CLOB
ต่อเนื่องกันได้ คลาส Java ใด ๆ ที่ใช้ java.io.Serializable VARBINARY (หรือ BLOB)
ก้อน java.sql.Clob CLOB
หยด java.sql.Blob หยด

ประเภทที่เกี่ยวข้องกับ JDK

ประเภทการทำแผนที่ ประเภท Java ประเภท ANSI SQL
ชั้นเรียน java.lang.Class VARCHAR
locale java.util.Locale VARCHAR
timezone java.util.TimeZone VARCHAR
currency java.util.Currency VARCHAR

Let us now take an example to understand how we can use Hibernate to provide Java persistence in a standalone application. We will go through the different steps involved in creating a Java Application using Hibernate technology.

Create POJO Classes

The first step in creating an application is to build the Java POJO class or classes, depending on the application that will be persisted to the database. Let us consider our Employee class with getXXX and setXXX methods to make it JavaBeans compliant class.

A POJO (Plain Old Java Object) is a Java object that doesn't extend or implement some specialized classes and interfaces respectively required by the EJB framework. All normal Java objects are POJO.

When you design a class to be persisted by Hibernate, it is important to provide JavaBeans compliant code as well as one attribute, which would work as index like id attribute in the Employee class.

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Create Database Tables

Second step would be creating tables in your database. There would be one table corresponding to each object, you are willing to provide persistence. Consider above objects need to be stored and retrieved into the following RDBMS table −

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Create Mapping Configuration File

This step is to create a mapping file that instructs Hibernate how to map the defined class or classes to the database tables.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

You should save the mapping document in a file with the format <classname>.hbm.xml. We saved our mapping document in the file Employee.hbm.xml. Let us see little detail about the mapping document −

  • The mapping document is an XML document having <hibernate-mapping> as the root element which contains all the <class> elements.

  • The <class> elements are used to define specific mappings from a Java classes to the database tables. The Java class name is specified using the name attribute of the class element and the database table name is specified using the table attribute.

  • The <meta> element is optional element and can be used to create the class description.

  • The <id> element maps the unique ID attribute in class to the primary key of the database table. The name attribute of the id element refers to the property in the class and the column attribute refers to the column in the database table. The type attribute holds the hibernate mapping type, this mapping types will convert from Java to SQL data type.

  • The <generator> element within the id element is used to generate the primary key values automatically. The class attribute of the generator element is set to native to let hibernate pick up either identity, sequence or hilo algorithm to create primary key depending upon the capabilities of the underlying database.

  • The <property> element is used to map a Java class property to a column in the database table. The name attribute of the element refers to the property in the class and the column attribute refers to the column in the database table. The type attribute holds the hibernate mapping type, this mapping types will convert from Java to SQL data type.

There are other attributes and elements available, which will be used in a mapping document and I would try to cover as many as possible while discussing other Hibernate related topics.

Create Application Class

Finally, we will create our application class with the main() method to run the application. We will use this application to save few Employee's records and then we will apply CRUD operations on those records.

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 10000);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down new list of the employees */
      ME.listEmployees();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }
   
   /* Method to  READ all the employees */
   public void listEmployees( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").list(); 
         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to UPDATE salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
		 session.update(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to DELETE an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

Compilation and Execution

Here are the steps to compile and run the above mentioned application. Make sure, you have set PATH and CLASSPATH appropriately before proceeding for the compilation and execution.

  • Create hibernate.cfg.xml configuration file as explained in configuration chapter.

  • Create Employee.hbm.xml mapping file as shown above.

  • Create Employee.java source file as shown above and compile it.

  • Create ManageEmployee.java source file as shown above and compile it.

  • Execute ManageEmployee binary to run the program.

You would get the following result, and records would be created in the EMPLOYEE table.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Zara  Last Name: Ali  Salary: 1000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
First Name: Zara  Last Name: Ali  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000

หากคุณตรวจสอบตารางพนักงานของคุณควรมีบันทึกดังต่อไปนี้ -

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara       | Ali       |   5000 |
| 31 | John       | Paul      |  10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec

mysql>

จนถึงตอนนี้เราได้เห็นการทำแผนที่ O / R ขั้นพื้นฐานโดยใช้โหมดไฮเบอร์เนต แต่มีหัวข้อการทำแผนที่ที่สำคัญที่สุดสามหัวข้อซึ่งเราต้องเรียนรู้โดยละเอียด

เหล่านี้คือ -

  • การทำแผนที่คอลเลกชัน
  • การแมปการเชื่อมโยงระหว่างคลาสเอนทิตีและ
  • การแมปส่วนประกอบ

การแมปคอลเล็กชัน

หากเอนทิตีหรือคลาสมีการรวบรวมค่าสำหรับตัวแปรเฉพาะเราสามารถแมปค่าเหล่านั้นโดยใช้อินเทอร์เฟซการรวบรวมใดก็ได้ที่มีอยู่ใน java ไฮเบอร์เนตสามารถคงอยู่ในอินสแตนซ์ของjava.util.Map, java.util.Set, java.util.SortedMap, java.util.SortedSet, java.util.Listและอื่น ๆ array ของเอนทิตีหรือค่าถาวร

ซีเนียร์ ประเภทคอลเลกชันและคำอธิบายการทำแผนที่
1 java.util.Set

สิ่งนี้ถูกแมปด้วยองค์ประกอบ <set> และเริ่มต้นด้วย java.util.HashSet

2 java.util.SortedSet

สิ่งนี้ถูกแมปด้วยองค์ประกอบ <set> และเริ่มต้นด้วย java.util.TreeSet sort แอตทริบิวต์สามารถตั้งค่าเป็นตัวเปรียบเทียบหรือลำดับตามธรรมชาติ

3 java.util.List

สิ่งนี้ถูกแมปด้วยองค์ประกอบ <list> และเริ่มต้นด้วย java.util.ArrayList

4 java.util.Collection

สิ่งนี้ถูกแมปด้วยองค์ประกอบ <bag> หรือ <ibag> และเริ่มต้นด้วย java.util.ArrayList

5 java.util.Map

สิ่งนี้ถูกแมปด้วยองค์ประกอบ <map> และเริ่มต้นด้วย java.util.HashMap

6 java.util.SortedMap

สิ่งนี้ถูกแมปด้วยองค์ประกอบ <map> และเริ่มต้นด้วย java.util.TreeMap sort แอตทริบิวต์สามารถตั้งค่าเป็นตัวเปรียบเทียบหรือลำดับตามธรรมชาติ

Hibernate รองรับอาร์เรย์ด้วย <primitive-array> สำหรับชนิดค่าดั้งเดิมของ Java และ <array> สำหรับสิ่งอื่น ๆ อย่างไรก็ตามพวกเขาไม่ค่อยได้ใช้ดังนั้นฉันจะไม่พูดถึงพวกเขาในบทช่วยสอนนี้

หากคุณต้องการแมปอินเทอร์เฟซคอลเลคชันที่ผู้ใช้กำหนดเองซึ่ง Hibernate ไม่รองรับโดยตรงคุณต้องบอก Hibernate เกี่ยวกับความหมายของคอลเล็กชันแบบกำหนดเองของคุณซึ่งไม่ใช่เรื่องง่ายและไม่แนะนำให้ใช้

การแมปสมาคม

การจับคู่ความเชื่อมโยงระหว่างคลาสเอนทิตีและความสัมพันธ์ระหว่างตารางคือจิตวิญญาณของ ORM ต่อไปนี้เป็นสี่วิธีในการแสดงความสำคัญของความสัมพันธ์ระหว่างวัตถุ การแมปการเชื่อมโยงสามารถเป็นแบบทิศทางเดียวและแบบสองทิศทาง

ซีเนียร์ ประเภทการทำแผนที่และคำอธิบาย
1 หลายต่อหนึ่ง

การแมปความสัมพันธ์แบบกลุ่มต่อหนึ่งโดยใช้ไฮเบอร์เนต

2 หนึ่งต่อหนึ่ง

การแมปความสัมพันธ์แบบหนึ่งต่อหนึ่งโดยใช้ไฮเบอร์เนต

3 หนึ่งต่อหลาย

การแมปความสัมพันธ์แบบหนึ่งต่อกลุ่มโดยใช้ไฮเบอร์เนต

4 หลายต่อหลายคน

การแมปความสัมพันธ์แบบกลุ่มต่อกลุ่มโดยใช้ไฮเบอร์เนต

การแมปส่วนประกอบ

เป็นไปได้อย่างมากที่คลาสเอนทิตีสามารถมีการอ้างอิงไปยังคลาสอื่นเป็นตัวแปรสมาชิก หากคลาสที่อ้างถึงไม่มีวงจรชีวิตของตัวเองและขึ้นอยู่กับวงจรชีวิตของคลาสเอนทิตีที่เป็นเจ้าของดังนั้นคลาสที่อ้างถึงจึงถูกเรียกว่าเป็นComponent class.

การแมปคอลเลคชันของคอมโพเนนต์ยังสามารถทำได้ในลักษณะเดียวกันเช่นเดียวกับการแมปคอลเลคชันปกติที่มีความแตกต่างของการกำหนดค่าเล็กน้อย เราจะเห็นการแมปทั้งสองนี้โดยละเอียดพร้อมตัวอย่าง

ซีเนียร์ ประเภทการทำแผนที่และคำอธิบาย
1 การแมปส่วนประกอบ

การแม็พสำหรับคลาสที่มีการอ้างอิงไปยังคลาสอื่นเป็นตัวแปรสมาชิก

จนถึงตอนนี้คุณได้เห็นแล้วว่า Hibernate ใช้ไฟล์แมป XML สำหรับการแปลงข้อมูลจาก POJO ไปยังตารางฐานข้อมูลอย่างไรและในทางกลับกัน คำอธิบายประกอบไฮเบอร์เนตเป็นวิธีใหม่ล่าสุดในการกำหนดการแมปโดยไม่ต้องใช้ไฟล์ XML คุณสามารถใช้คำอธิบายประกอบนอกเหนือจากหรือใช้แทนข้อมูลเมตาการแมป XML ได้

คำอธิบายประกอบไฮเบอร์เนตเป็นวิธีที่มีประสิทธิภาพในการจัดเตรียมข้อมูลเมตาสำหรับการแมปวัตถุและตารางเชิงสัมพันธ์ ข้อมูลเมตาทั้งหมดรวมอยู่ในไฟล์ POJO java พร้อมกับรหัสซึ่งช่วยให้ผู้ใช้เข้าใจโครงสร้างตารางและ POJO พร้อมกันในระหว่างการพัฒนา

หากคุณจะทำให้แอปพลิเคชันของคุณพกพาไปยังแอปพลิเคชัน ORM ที่เข้ากันได้กับ EJB 3 อื่น ๆ คุณต้องใช้คำอธิบายประกอบเพื่อแสดงข้อมูลการทำแผนที่ แต่ถ้าคุณต้องการความยืดหยุ่นมากขึ้นคุณควรใช้การแมปที่ใช้ XML

การตั้งค่าสภาพแวดล้อมสำหรับคำอธิบายประกอบไฮเบอร์เนต

ก่อนอื่นคุณต้องตรวจสอบให้แน่ใจว่าคุณใช้ JDK 5.0 ไม่เช่นนั้นคุณต้องอัปเกรด JDK ของคุณเป็น JDK 5.0 เพื่อใช้ประโยชน์จากการสนับสนุนดั้งเดิมสำหรับคำอธิบายประกอบ

ประการที่สองคุณจะต้องติดตั้งแพ็คเกจการแจกจ่ายคำอธิบายประกอบไฮเบอร์เนต 3.x ซึ่งมีให้จาก sourceforge: ( ดาวน์โหลดคำอธิบายประกอบไฮเบอร์เนต ) และคัดลอกhibernate-annotations.jar, lib/hibernate-comons-annotations.jar และ lib/ejb3-persistence.jar จากการกระจายคำอธิบายประกอบไฮเบอร์เนตไปยัง CLASSPATH ของคุณ

ตัวอย่างคลาสที่มีคำอธิบายประกอบ

ดังที่ฉันได้กล่าวไว้ข้างต้นในขณะที่ทำงานกับ Hibernate Annotation ข้อมูลเมตาทั้งหมดจะรวมอยู่ในไฟล์ POJO java พร้อมกับรหัสซึ่งจะช่วยให้ผู้ใช้เข้าใจโครงสร้างตารางและ POJO พร้อมกันในระหว่างการพัฒนา

พิจารณาว่าเราจะใช้ตารางพนักงานต่อไปนี้เพื่อจัดเก็บวัตถุของเรา -

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

ต่อไปนี้คือการแมปคลาสพนักงานพร้อมคำอธิบายประกอบเพื่อแมปวัตถุด้วยตารางพนักงานที่กำหนดไว้ -

import javax.persistence.*;

@Entity
@Table(name = "EMPLOYEE")
public class Employee {
   @Id @GeneratedValue
   @Column(name = "id")
   private int id;

   @Column(name = "first_name")
   private String firstName;

   @Column(name = "last_name")
   private String lastName;

   @Column(name = "salary")
   private int salary;  

   public Employee() {}
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

ไฮเบอร์เนตตรวจพบว่าคำอธิบายประกอบ @Id อยู่บนฟิลด์และสันนิษฐานว่าควรเข้าถึงคุณสมบัติของอ็อบเจ็กต์โดยตรงผ่านฟิลด์ที่รันไทม์ หากคุณวางคำอธิบายประกอบ @Id ไว้บนเมธอด getId () คุณจะเปิดใช้งานการเข้าถึงคุณสมบัติผ่านเมธอด getter และ setter ตามค่าเริ่มต้น ดังนั้นคำอธิบายประกอบอื่น ๆ ทั้งหมดจะถูกวางไว้บนฟิลด์หรือวิธีการ getter ตามกลยุทธ์ที่เลือก

ส่วนต่อไปนี้จะอธิบายคำอธิบายประกอบที่ใช้ในชั้นเรียนข้างต้น

คำอธิบายประกอบ @ เอนทิตี

คำอธิบายประกอบมาตรฐาน EJB 3 มีอยู่ในไฟล์ javax.persistenceเราจึงนำเข้าแพ็คเกจนี้เป็นขั้นตอนแรก ประการที่สองเราใช้ไฟล์@Entity คำอธิบายประกอบไปยังคลาส Employee ซึ่งทำเครื่องหมายคลาสนี้เป็นเอนทิตี bean ดังนั้นจึงต้องมีตัวสร้างที่ไม่มีอาร์กิวเมนต์ที่มองเห็นได้โดยมีขอบเขตที่มีการป้องกันเป็นอย่างน้อย

@ คำอธิบายประกอบตาราง

คำอธิบายประกอบ @Table ช่วยให้คุณระบุรายละเอียดของตารางที่จะใช้เพื่อคงเอนทิตีไว้ในฐานข้อมูล

คำอธิบายประกอบ @Table มีแอตทริบิวต์สี่รายการช่วยให้คุณสามารถแทนที่ชื่อของตารางแค็ตตาล็อกและสคีมาและบังคับใช้ข้อ จำกัด เฉพาะกับคอลัมน์ในตาราง ตอนนี้เราใช้แค่ชื่อตารางซึ่งก็คือ EMPLOYEE

@Id และ @GeneratedValue Annotations

แต่ละเอนทิตี bean จะมีคีย์หลักซึ่งคุณใส่คำอธิบายประกอบในคลาสด้วย @Idคำอธิบายประกอบ คีย์หลักอาจเป็นฟิลด์เดียวหรือหลายฟิลด์รวมกันก็ได้ขึ้นอยู่กับโครงสร้างตารางของคุณ

ตามค่าเริ่มต้นคำอธิบายประกอบ @Id จะกำหนดกลยุทธ์การสร้างคีย์หลักที่เหมาะสมที่สุดที่จะใช้โดยอัตโนมัติ แต่คุณสามารถแทนที่สิ่งนี้ได้โดยใช้ @GeneratedValue คำอธิบายประกอบซึ่งใช้สองพารามิเตอร์ strategy และ generatorที่ฉันจะไม่พูดถึงในที่นี้ดังนั้นให้เราใช้เฉพาะกลยุทธ์การสร้างคีย์เริ่มต้นเท่านั้น การให้ Hibernate กำหนดประเภทของเครื่องกำเนิดไฟฟ้าที่จะใช้ทำให้โค้ดของคุณพกพาได้ระหว่างฐานข้อมูลต่างๆ

@ คอลัมน์คำอธิบายประกอบ

คำอธิบายประกอบ @Column ใช้เพื่อระบุรายละเอียดของคอลัมน์ที่จะแมปฟิลด์หรือคุณสมบัติ คุณสามารถใช้คำอธิบายประกอบคอลัมน์กับแอตทริบิวต์ที่ใช้บ่อยดังต่อไปนี้ -

  • name แอตทริบิวต์อนุญาตให้ระบุชื่อของคอลัมน์อย่างชัดเจน

  • length แอตทริบิวต์อนุญาตขนาดของคอลัมน์ที่ใช้ในการแมปค่าโดยเฉพาะสำหรับค่า String

  • nullable แอตทริบิวต์อนุญาตให้ทำเครื่องหมายคอลัมน์ไม่เป็นโมฆะเมื่อสร้างสคีมา

  • unique แอตทริบิวต์อนุญาตให้ทำเครื่องหมายคอลัมน์ว่ามีเฉพาะค่าที่ไม่ซ้ำกัน

สร้างคลาสแอปพลิเคชัน

สุดท้ายเราจะสร้างคลาสแอปพลิเคชันของเราด้วยเมธอด main () เพื่อเรียกใช้แอปพลิเคชัน เราจะใช้แอปพลิเคชันนี้เพื่อบันทึกประวัติของพนักงานเพียงไม่กี่คนจากนั้นเราจะใช้การดำเนินการ CRUD กับบันทึกเหล่านั้น

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new AnnotationConfiguration().
                   configure().
                   //addPackage("com.xyz") //add package if used.
                   addAnnotatedClass(Employee.class).
                   buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 10000);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down new list of the employees */
      ME.listEmployees();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee();
         employee.setFirstName(fname);
         employee.setLastName(lname);
         employee.setSalary(salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }
   
   /* Method to  READ all the employees */
   public void listEmployees( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").list(); 
         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to UPDATE salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
		 session.update(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to DELETE an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

การกำหนดค่าฐานข้อมูล

ตอนนี้ให้เราสร้าง hibernate.cfg.xml ไฟล์คอนฟิกูเรชันเพื่อกำหนดพารามิเตอร์ที่เกี่ยวข้องกับฐานข้อมูล

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
   
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>

      <!-- Assume students is the database name -->
   
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
   
      <property name = "hibernate.connection.username">
         root
      </property>
   
      <property name = "hibernate.connection.password">
         cohondob
      </property>

   </session-factory>
</hibernate-configuration>

การรวบรวมและการดำเนินการ

นี่คือขั้นตอนในการรวบรวมและเรียกใช้แอปพลิเคชันที่กล่าวถึงข้างต้น ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่า PATH และ CLASSPATH อย่างเหมาะสมก่อนดำเนินการรวบรวมและดำเนินการ

  • ลบไฟล์การแม็พ Employee.hbm.xml จากพา ธ

  • สร้างไฟล์ซอร์ส Employee.java ตามที่แสดงด้านบนและคอมไพล์

  • สร้างไฟล์ต้นฉบับ ManageEmployee.java ตามที่แสดงด้านบนและคอมไพล์

  • ดำเนินการไบนารี ManageEmployee เพื่อรันโปรแกรม

คุณจะได้รับผลลัพธ์ดังต่อไปนี้และบันทึกจะถูกสร้างขึ้นในตาราง EMPLOYEE

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Zara  Last Name: Ali  Salary: 1000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
First Name: Zara  Last Name: Ali  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000

หากคุณตรวจสอบตารางพนักงานของคุณควรมีบันทึกดังต่อไปนี้ -

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara       | Ali       |   5000 |
| 31 | John       | Paul      |  10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec

mysql>

Hibernate Query Language (HQL) เป็นภาษาเคียวรีเชิงวัตถุคล้ายกับ SQL แต่แทนที่จะทำงานบนตารางและคอลัมน์ HQL จะทำงานกับอ็อบเจ็กต์แบบถาวรและคุณสมบัติของมัน แบบสอบถาม HQL ถูกแปลโดย Hibernate เป็นแบบสอบถาม SQL ทั่วไปซึ่งจะดำเนินการกับฐานข้อมูล

แม้ว่าคุณจะสามารถใช้คำสั่ง SQL โดยตรงกับ Hibernate โดยใช้ Native SQL แต่ฉันขอแนะนำให้ใช้ HQL ทุกครั้งที่ทำได้เพื่อหลีกเลี่ยงความยุ่งยากในการเคลื่อนย้ายฐานข้อมูลและใช้ประโยชน์จากกลยุทธ์การสร้าง SQL และแคชของ Hibernate

คีย์เวิร์ดเช่น SELECT, FROM และ WHERE เป็นต้นไม่คำนึงถึงขนาดตัวพิมพ์ แต่คุณสมบัติเช่นชื่อตารางและคอลัมน์จะพิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ใน HQL

จากข้อ

คุณจะใช้ FROMประโยคถ้าคุณต้องการโหลดอ็อบเจ็กต์ถาวรที่สมบูรณ์ลงในหน่วยความจำ ต่อไปนี้เป็นไวยากรณ์ง่ายๆของการใช้ FROM clause -

String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

หากคุณต้องการกำหนดชื่อคลาสใน HQL ให้ครบถ้วนเพียงระบุแพ็คเกจและชื่อคลาสดังนี้ -

String hql = "FROM com.hibernatebook.criteria.Employee";
Query query = session.createQuery(hql);
List results = query.list();

เป็นข้อ

ASสามารถใช้ clause เพื่อกำหนดนามแฝงให้กับคลาสในแบบสอบถาม HQL ของคุณโดยเฉพาะอย่างยิ่งเมื่อคุณมีคิวรียาว ๆ ตัวอย่างเช่นตัวอย่างง่ายๆก่อนหน้านี้ของเราจะเป็นดังต่อไปนี้ -

String hql = "FROM Employee AS E";
Query query = session.createQuery(hql);
List results = query.list();

AS คีย์เวิร์ดเป็นทางเลือกและคุณยังสามารถระบุนามแฝงหลังชื่อคลาสได้โดยตรงดังนี้ -

String hql = "FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

เลือกประโยค

SELECTอนุประโยคให้การควบคุมชุดผลลัพธ์มากขึ้นจากนั้นจากอนุประโยค หากคุณต้องการได้รับคุณสมบัติบางอย่างของอ็อบเจ็กต์แทนที่จะเป็นอ็อบเจ็กต์ที่สมบูรณ์ให้ใช้ส่วนคำสั่ง SELECT ต่อไปนี้เป็นไวยากรณ์อย่างง่ายของการใช้คำสั่ง SELECT เพื่อรับฟิลด์ first_name ของอ็อบเจ็กต์พนักงาน -

String hql = "SELECT E.firstName FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

เป็นที่น่าสังเกตว่า Employee.firstName เป็นคุณสมบัติของอ็อบเจ็กต์ Employee แทนที่จะเป็นฟิลด์ของตาราง EMPLOYEE

WHERE ข้อ

ถ้าคุณต้องการ จำกัด ออบเจ็กต์เฉพาะที่ส่งคืนจากที่เก็บข้อมูลให้แคบลงให้ใช้คำสั่ง WHERE ต่อไปนี้เป็นไวยากรณ์ง่ายๆของการใช้คำสั่ง WHERE -

String hql = "FROM Employee E WHERE E.id = 10";
Query query = session.createQuery(hql);
List results = query.list();

สั่งซื้อตามข้อ

ในการจัดเรียงผลลัพธ์ของแบบสอบถาม HQL ของคุณคุณจะต้องใช้ไฟล์ ORDER BYอนุประโยค คุณสามารถจัดลำดับผลลัพธ์โดยคุณสมบัติใด ๆ บนวัตถุในชุดผลลัพธ์จากน้อยไปหามาก (ASC) หรือจากมากไปหาน้อย (DESC) ต่อไปนี้เป็นไวยากรณ์ง่ายๆของการใช้คำสั่ง ORDER BY -

String hql = "FROM Employee E WHERE E.id > 10 ORDER BY E.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();

หากคุณต้องการจัดเรียงตามคุณสมบัติมากกว่าหนึ่งรายการคุณก็แค่เพิ่มคุณสมบัติเพิ่มเติมที่ส่วนท้ายของคำสั่งตามอนุประโยคโดยคั่นด้วยลูกน้ำดังนี้ -

String hql = "FROM Employee E WHERE E.id > 10 " +
             "ORDER BY E.firstName DESC, E.salary DESC ";
Query query = session.createQuery(hql);
List results = query.list();

จัดกลุ่มตามข้อ

ประโยคนี้ช่วยให้ Hibernate ดึงข้อมูลจากฐานข้อมูลและจัดกลุ่มตามค่าของแอตทริบิวต์และโดยทั่วไปจะใช้ผลลัพธ์เพื่อรวมค่าการรวม ต่อไปนี้เป็นไวยากรณ์ง่ายๆของการใช้ GROUP BY clause -

String hql = "SELECT SUM(E.salary), E.firtName FROM Employee E " +
             "GROUP BY E.firstName";
Query query = session.createQuery(hql);
List results = query.list();

การใช้พารามิเตอร์ที่มีชื่อ

Hibernate รองรับพารามิเตอร์ที่มีชื่อในการสืบค้น HQL สิ่งนี้ทำให้การเขียนแบบสอบถาม HQL ที่ยอมรับอินพุตจากผู้ใช้เป็นเรื่องง่ายและคุณไม่จำเป็นต้องป้องกันการโจมตีด้วยการฉีด SQL ต่อไปนี้เป็นไวยากรณ์ง่ายๆของการใช้พารามิเตอร์ที่มีชื่อ -

String hql = "FROM Employee E WHERE E.id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id",10);
List results = query.list();

ปรับปรุงข้อ

การอัปเดตจำนวนมากเป็นสิ่งใหม่สำหรับ HQL ที่มี Hibernate 3 และการลบการทำงานใน Hibernate 3 แตกต่างจากที่ทำใน Hibernate 2 ขณะนี้อินเทอร์เฟซ Query มีวิธีการที่เรียกว่า executeUpdate () สำหรับการเรียกใช้คำสั่ง HQL UPDATE หรือ DELETE

UPDATEสามารถใช้ clause เพื่ออัพเดตคุณสมบัติอย่างน้อยหนึ่งอย่างของอ็อบเจ็กต์หนึ่งหรือหลายอ็อบเจ็กต์ ต่อไปนี้เป็นไวยากรณ์ง่ายๆของการใช้ UPDATE clause -

String hql = "UPDATE Employee set salary = :salary "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("salary", 1000);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

ลบประโยค

DELETEอนุประโยคสามารถใช้เพื่อลบวัตถุอย่างน้อยหนึ่งชิ้น ต่อไปนี้เป็นไวยากรณ์อย่างง่ายของการใช้ DELETE clause -

String hql = "DELETE FROM Employee "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

แทรกข้อ

รองรับ HQL INSERT INTOอนุประโยคเฉพาะที่สามารถแทรกระเบียนจากวัตถุหนึ่งไปยังวัตถุอื่น ต่อไปนี้เป็นไวยากรณ์ง่ายๆของการใช้คำสั่ง INSERT INTO -

String hql = "INSERT INTO Employee(firstName, lastName, salary)"  + 
             "SELECT firstName, lastName, salary FROM old_employee";
Query query = session.createQuery(hql);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

วิธีการรวม

HQL รองรับวิธีการรวมที่หลากหลายเช่นเดียวกับ SQL พวกเขาทำงานในลักษณะเดียวกันใน HQL เช่นเดียวกับใน SQL และต่อไปนี้คือรายการฟังก์ชันที่มี -

ซีเนียร์ ฟังก์ชั่นและคำอธิบาย
1

avg(property name)

ค่าเฉลี่ยของมูลค่าทรัพย์สิน

2

count(property name or *)

จำนวนครั้งที่คุณสมบัติเกิดขึ้นในผลลัพธ์

3

max(property name)

ค่าสูงสุดของค่าคุณสมบัติ

4

min(property name)

ค่าต่ำสุดของค่าคุณสมบัติ

5

sum(property name)

ผลรวมของค่าคุณสมบัติ

distinctคำหลักจะนับเฉพาะค่าที่ไม่ซ้ำกันในชุดแถว ข้อความค้นหาต่อไปนี้จะส่งคืนเฉพาะจำนวนที่ไม่ซ้ำกัน -

String hql = "SELECT count(distinct E.firstName) FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

การแบ่งหน้าโดยใช้แบบสอบถาม

อินเทอร์เฟซแบบสอบถามสำหรับการแบ่งหน้ามีสองวิธี

ซีเนียร์ วิธีการและคำอธิบาย
1

Query setFirstResult(int startPosition)

วิธีนี้ใช้จำนวนเต็มแทนแถวแรกในชุดผลลัพธ์ของคุณโดยเริ่มจากแถว 0

2

Query setMaxResults(int maxResult)

วิธีนี้จะบอกให้ Hibernate ดึงตัวเลขคงที่ maxResults ของวัตถุ

ด้วยการใช้สองวิธีข้างต้นร่วมกันเราสามารถสร้างส่วนประกอบการเพจในเว็บหรือแอปพลิเคชัน Swing ของเรา ต่อไปนี้เป็นตัวอย่างซึ่งคุณสามารถขยายเพื่อดึงข้อมูลครั้งละ 10 แถว -

String hql = "FROM Employee";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(10);
List results = query.list();

ไฮเบอร์เนตมีวิธีอื่นในการจัดการวัตถุและข้อมูลที่มีอยู่ในตาราง RDBMS วิธีการหนึ่งคือ Criteria API ซึ่งช่วยให้คุณสามารถสร้างอ็อบเจ็กต์เคียวรีเกณฑ์โดยใช้โปรแกรมโดยใช้กฎการกรองและเงื่อนไขเชิงตรรกะ

ไฮเบอร์เนต Session อินเทอร์เฟซให้ createCriteria() ซึ่งสามารถใช้สร้างไฟล์ Criteria วัตถุที่ส่งคืนอินสแตนซ์ของคลาสของออบเจ็กต์การคงอยู่เมื่อแอปพลิเคชันของคุณเรียกใช้แบบสอบถามเกณฑ์

ต่อไปนี้เป็นตัวอย่างที่ง่ายที่สุดของแบบสอบถามเกณฑ์ซึ่งจะส่งคืนทุกออบเจ็กต์ที่สอดคล้องกับคลาสพนักงาน

Criteria cr = session.createCriteria(Employee.class);
List results = cr.list();

ข้อ จำกัด กับเกณฑ์

คุณสามารถใช้ได้ add() มีวิธีการสำหรับ Criteriaวัตถุเพื่อเพิ่มข้อ จำกัด สำหรับแบบสอบถามเกณฑ์ ต่อไปนี้เป็นตัวอย่างการเพิ่มข้อ จำกัด ในการส่งคืนระเบียนโดยมีเงินเดือนเท่ากับ 2000 -

Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.eq("salary", 2000));
List results = cr.list();

ต่อไปนี้เป็นตัวอย่างเพิ่มเติมบางส่วนที่ครอบคลุมสถานการณ์ต่างๆและสามารถใช้ได้ตามความต้องการ -

Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To get records having salary less than 2000
cr.add(Restrictions.lt("salary", 2000));

// To get records having fistName starting with zara
cr.add(Restrictions.like("firstName", "zara%"));

// Case sensitive form of the above restriction.
cr.add(Restrictions.ilike("firstName", "zara%"));

// To get records having salary in between 1000 and 2000
cr.add(Restrictions.between("salary", 1000, 2000));

// To check if the given property is null
cr.add(Restrictions.isNull("salary"));

// To check if the given property is not null
cr.add(Restrictions.isNotNull("salary"));

// To check if the given property is empty
cr.add(Restrictions.isEmpty("salary"));

// To check if the given property is not empty
cr.add(Restrictions.isNotEmpty("salary"));

คุณสามารถสร้างเงื่อนไข AND หรือ OR โดยใช้ข้อ จำกัด LogicalExpression ดังนี้ -

Criteria cr = session.createCriteria(Employee.class);

Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");

// To get records matching with OR conditions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );

// To get records matching with AND conditions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );

List results = cr.list();

แม้ว่าเงื่อนไขทั้งหมดข้างต้นจะสามารถใช้ได้โดยตรงกับ HQL ตามที่อธิบายไว้ในบทช่วยสอนก่อนหน้านี้

การแบ่งหน้าโดยใช้เกณฑ์

อินเทอร์เฟซเกณฑ์สำหรับการแบ่งหน้ามีสองวิธี

ซีเนียร์ วิธีการและคำอธิบาย
1

public Criteria setFirstResult(int firstResult)

วิธีนี้ใช้จำนวนเต็มแทนแถวแรกในชุดผลลัพธ์ของคุณโดยเริ่มจากแถว 0

2

public Criteria setMaxResults(int maxResults)

วิธีนี้จะบอกให้ Hibernate ดึงตัวเลขคงที่ maxResults ของวัตถุ

ด้วยการใช้สองวิธีข้างต้นร่วมกันเราสามารถสร้างส่วนประกอบการเพจในเว็บหรือแอปพลิเคชัน Swing ของเรา ต่อไปนี้เป็นตัวอย่างซึ่งคุณสามารถขยายเพื่อดึงข้อมูลครั้งละ 10 แถว -

Criteria cr = session.createCriteria(Employee.class);
cr.setFirstResult(1);
cr.setMaxResults(10);
List results = cr.list();

การเรียงลำดับผลลัพธ์

Criteria API จัดเตรียม org.hibernate.criterion.Orderคลาสเพื่อเรียงลำดับผลลัพธ์ของคุณตามลำดับจากน้อยไปหามากหรือจากมากไปหาน้อยตามคุณสมบัติอย่างใดอย่างหนึ่งของวัตถุของคุณ ตัวอย่างนี้แสดงให้เห็นว่าคุณจะใช้คลาส Order เพื่อเรียงลำดับชุดผลลัพธ์อย่างไร -

Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To sort records in descening order
cr.addOrder(Order.desc("salary"));

// To sort records in ascending order
cr.addOrder(Order.asc("salary"));

List results = cr.list();

การคาดการณ์และการรวม

Criteria API จัดเตรียม org.hibernate.criterion.Projectionsคลาสซึ่งสามารถใช้เพื่อรับค่าเฉลี่ยสูงสุดหรือต่ำสุดของค่าคุณสมบัติ คลาส Projections คล้ายกับคลาส Restrictions เนื่องจากมีวิธีการโรงงานแบบคงที่หลายวิธีสำหรับการได้รับProjection ตัวอย่าง.

ต่อไปนี้เป็นตัวอย่างบางส่วนที่ครอบคลุมสถานการณ์ต่างๆและสามารถใช้ได้ตามความต้องการ -

Criteria cr = session.createCriteria(Employee.class);

// To get total row count.
cr.setProjection(Projections.rowCount());

// To get average of a property.
cr.setProjection(Projections.avg("salary"));

// To get distinct count of a property.
cr.setProjection(Projections.countDistinct("firstName"));

// To get maximum of a property.
cr.setProjection(Projections.max("salary"));

// To get minimum of a property.
cr.setProjection(Projections.min("salary"));

// To get sum of a property.
cr.setProjection(Projections.sum("salary"));

ตัวอย่างแบบสอบถามเกณฑ์

พิจารณาคลาส POJO ต่อไปนี้ -

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

ให้เราสร้างตาราง EMPLOYEE ต่อไปนี้เพื่อจัดเก็บวัตถุพนักงาน -

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

ต่อไปนี้จะเป็นไฟล์การแมป

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

สุดท้ายเราจะสร้างคลาสแอปพลิเคชันของเราด้วยเมธอด main () เพื่อเรียกใช้แอปพลิเคชันที่เราจะใช้ Criteria แบบสอบถาม -

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Projections;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 5000);
      Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);

      /* List down all the employees */
      ME.listEmployees();

      /* Print Total employee's count */
      ME.countEmployee();

      /* Print Total salary */
      ME.totalSalary();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }

   /* Method to  READ all the employees having salary more than 2000 */
   public void listEmployees( ) {
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Criteria cr = session.createCriteria(Employee.class);
         // Add restriction.
         cr.add(Restrictions.gt("salary", 2000));
         List employees = cr.list();

         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to print total number of records */
   public void countEmployee(){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Criteria cr = session.createCriteria(Employee.class);

         // To get total row count.
         cr.setProjection(Projections.rowCount());
         List rowCount = cr.list();

         System.out.println("Total Coint: " + rowCount.get(0) );
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
  
   /* Method to print sum of salaries */
   public void totalSalary(){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Criteria cr = session.createCriteria(Employee.class);

         // To get total salary.
         cr.setProjection(Projections.sum("salary"));
         List totalSalary = cr.list();

         System.out.println("Total Salary: " + totalSalary.get(0) );
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

การรวบรวมและการดำเนินการ

นี่คือขั้นตอนในการรวบรวมและเรียกใช้แอปพลิเคชันที่กล่าวถึงข้างต้น ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่า PATH และ CLASSPATH อย่างเหมาะสมก่อนดำเนินการรวบรวมและดำเนินการ

  • สร้างไฟล์คอนฟิกูเรชัน hibernate.cfg.xml ตามที่อธิบายไว้ในบทการกำหนดค่า

  • สร้างไฟล์การแมป Employee.hbm.xml ดังที่แสดงด้านบน

  • สร้างไฟล์ซอร์ส Employee.java ตามที่แสดงด้านบนและคอมไพล์

  • สร้างไฟล์ต้นฉบับ ManageEmployee.java ตามที่แสดงด้านบนและคอมไพล์

  • ดำเนินการไบนารี ManageEmployee เพื่อรันโปรแกรม

คุณจะได้รับผลลัพธ์ดังต่อไปนี้และบันทึกจะถูกสร้างขึ้นในตาราง EMPLOYEE

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 5000
First Name: Mohd  Last Name: Yasee  Salary: 3000
Total Coint: 4
Total Salary: 15000

หากคุณตรวจสอบตารางพนักงานของคุณควรมีบันทึกดังต่อไปนี้

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 14 | Zara       | Ali       |   2000 |
| 15 | Daisy      | Das       |   5000 |
| 16 | John       | Paul      |   5000 |
| 17 | Mohd       | Yasee     |   3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)
mysql>

คุณสามารถใช้ SQL แบบเนทีฟเพื่อแสดงคิวรีฐานข้อมูลหากคุณต้องการใช้คุณสมบัติเฉพาะของฐานข้อมูลเช่นคำแนะนำการสืบค้นหรือคีย์เวิร์ด CONNECT ใน Oracle Hibernate 3.x ช่วยให้คุณระบุ SQL ที่เขียนด้วยลายมือรวมถึงโพรซีเดอร์ที่จัดเก็บไว้สำหรับการสร้างอัปเดตลบและโหลดการดำเนินการทั้งหมด

แอปพลิเคชันของคุณจะสร้างแบบสอบถาม SQL ดั้งเดิมจากเซสชันด้วยไฟล์ createSQLQuery() วิธีการบนอินเทอร์เฟซเซสชัน -

public SQLQuery createSQLQuery(String sqlString) throws HibernateException

หลังจากที่คุณส่งสตริงที่มีคิวรี SQL ไปยังเมธอด createSQLQuery () คุณสามารถเชื่อมโยงผลลัพธ์ SQL กับเอนทิตี Hibernate ที่มีอยู่การรวมหรือผลลัพธ์สเกลาร์โดยใช้เมธอด addEntity (), addJoin () และ addScalar () ตามลำดับ

แบบสอบถาม Scalar

แบบสอบถาม SQL ขั้นพื้นฐานที่สุดคือการรับรายการสเกลาร์ (ค่า) จากตารางอย่างน้อยหนึ่งตาราง ต่อไปนี้เป็นไวยากรณ์สำหรับการใช้ SQL ดั้งเดิมสำหรับค่าสเกลาร์ -

String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();

แบบสอบถามเอนทิตี

คำค้นหาข้างต้นเป็นข้อมูลเกี่ยวกับการส่งคืนค่าสเกลาร์โดยทั่วไปจะส่งคืนค่า "ดิบ" จากชุดผลลัพธ์ ต่อไปนี้เป็นไวยากรณ์เพื่อรับเอนทิตีอ็อบเจ็กต์โดยรวมจากเคียวรี SQL ดั้งเดิมผ่าน addEntity ()

String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List results = query.list();

แบบสอบถาม SQL ที่ตั้งชื่อ

ต่อไปนี้เป็นไวยากรณ์ในการรับเอนทิตีอ็อบเจ็กต์จากเคียวรี SQL ดั้งเดิมผ่าน addEntity () และใช้คิวรี SQL ที่มีชื่อ

String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list();

ตัวอย่าง Native SQL

พิจารณาคลาส POJO ต่อไปนี้ -

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

ให้เราสร้างตาราง EMPLOYEE ต่อไปนี้เพื่อจัดเก็บวัตถุพนักงาน -

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

ต่อไปนี้จะเป็นไฟล์การแมป -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

สุดท้ายเราจะสร้างคลาสแอปพลิเคชันของเราด้วยเมธอด main () เพื่อเรียกใช้แอปพลิเคชันที่เราจะใช้ Native SQL แบบสอบถาม -

import java.util.*; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.SQLQuery;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 5000);
      Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);

      /* List down employees and their salary using Scalar Query */
      ME.listEmployeesScalar();

      /* List down complete employees information using Entity Query */
      ME.listEmployeesEntity();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }

   /* Method to  READ all the employees using Scalar Query */
   public void listEmployeesScalar( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         String sql = "SELECT first_name, salary FROM EMPLOYEE";
         SQLQuery query = session.createSQLQuery(sql);
         query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
         List data = query.list();

         for(Object object : data) {
            Map row = (Map)object;
            System.out.print("First Name: " + row.get("first_name")); 
            System.out.println(", Salary: " + row.get("salary")); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }

   /* Method to READ all the employees using Entity Query */
   public void listEmployeesEntity( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         String sql = "SELECT * FROM EMPLOYEE";
         SQLQuery query = session.createSQLQuery(sql);
         query.addEntity(Employee.class);
         List employees = query.list();

         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

การรวบรวมและการดำเนินการ

นี่คือขั้นตอนในการรวบรวมและเรียกใช้แอปพลิเคชันที่กล่าวถึงข้างต้น ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่า PATH และ CLASSPATH อย่างเหมาะสมก่อนดำเนินการรวบรวมและดำเนินการ

  • สร้างไฟล์คอนฟิกูเรชัน hibernate.cfg.xml ตามที่อธิบายไว้ในบทการกำหนดค่า

  • สร้างไฟล์การแมป Employee.hbm.xml ดังที่แสดงด้านบน

  • สร้างไฟล์ซอร์ส Employee.java ตามที่แสดงด้านบนและคอมไพล์

  • สร้างไฟล์ต้นฉบับ ManageEmployee.java ตามที่แสดงด้านบนและคอมไพล์

  • ดำเนินการไบนารี ManageEmployee เพื่อรันโปรแกรม

คุณจะได้รับผลลัพธ์ดังต่อไปนี้และบันทึกจะถูกสร้างขึ้นในตาราง EMPLOYEE

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Zara, Salary: 2000
First Name: Daisy, Salary: 5000
First Name: John, Salary: 5000
First Name: Mohd, Salary: 3000
First Name: Zara  Last Name: Ali  Salary: 2000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 5000
First Name: Mohd  Last Name: Yasee  Salary: 3000

หากคุณตรวจสอบตารางพนักงานของคุณควรมีบันทึกดังต่อไปนี้ -

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 26 | Zara       | Ali       |   2000 |
| 27 | Daisy      | Das       |   5000 |
| 28 | John       | Paul      |   5000 |
| 29 | Mohd       | Yasee     |   3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)
mysql>

การแคชเป็นกลไกในการเพิ่มประสิทธิภาพของระบบ เป็นหน่วยความจำบัฟเฟอร์ที่อยู่ระหว่างแอปพลิเคชันและฐานข้อมูล หน่วยความจำแคชจัดเก็บรายการข้อมูลที่ใช้ล่าสุดเพื่อลดจำนวนการเข้าถึงฐานข้อมูลให้ได้มากที่สุด

การแคชมีความสำคัญต่อไฮเบอร์เนตเช่นกัน มันใช้รูปแบบการแคชหลายระดับตามที่อธิบายไว้ด้านล่าง -

แคชระดับแรก

แคชระดับแรกคือแคชของเซสชันและเป็นแคชบังคับซึ่งการร้องขอทั้งหมดจะต้องผ่าน วัตถุเซสชันเก็บวัตถุไว้ภายใต้อำนาจของตัวเองก่อนที่จะส่งไปยังฐานข้อมูล

หากคุณออกการอัปเดตหลายรายการให้กับอ็อบเจ็กต์ไฮเบอร์เนตจะพยายามชะลอการอัปเดตให้นานที่สุดเพื่อลดจำนวนการอัพเดตคำสั่ง SQL ที่ออก หากคุณปิดเซสชันอ็อบเจ็กต์ทั้งหมดที่แคชไว้จะสูญหายและยังคงอยู่หรืออัพเดตในฐานข้อมูล

แคชระดับที่สอง

แคชระดับที่สองเป็นแคชที่เป็นทางเลือกและแคชระดับแรกจะได้รับการปรึกษาเสมอก่อนที่จะพยายามค้นหาวัตถุในแคชระดับที่สอง แคชระดับที่สองสามารถกำหนดค่าเป็นรายคลาสและต่อคอลเลกชันและส่วนใหญ่รับผิดชอบในการแคชอ็อบเจ็กต์ข้ามเซสชัน

แคชของบุคคลที่สามสามารถใช้กับ Hibernate ได้ อันorg.hibernate.cache.CacheProvider มีการจัดเตรียมอินเทอร์เฟซซึ่งจะต้องดำเนินการเพื่อให้ Hibernate มีส่วนจัดการกับการใช้งานแคช

แคชระดับการสืบค้น

ไฮเบอร์เนตยังใช้แคชสำหรับชุดผลลัพธ์การค้นหาที่รวมอย่างใกล้ชิดกับแคชระดับที่สอง

นี่เป็นคุณลักษณะที่เป็นทางเลือกและต้องการพื้นที่แคชฟิสิคัลเพิ่มเติมสองพื้นที่ที่เก็บผลลัพธ์ของคิวรีที่แคชไว้และการประทับเวลาเมื่อตารางได้รับการอัปเดตครั้งล่าสุด สิ่งนี้มีประโยชน์สำหรับแบบสอบถามที่เรียกใช้บ่อยด้วยพารามิเตอร์เดียวกันเท่านั้น

แคชระดับที่สอง

ไฮเบอร์เนตใช้แคชระดับแรกตามค่าเริ่มต้นและคุณไม่ต้องทำอะไรเพื่อใช้แคชระดับแรก ตรงไปที่แคชระดับสองที่เป็นทางเลือก ไม่ใช่ทุกคลาสที่จะได้รับประโยชน์จากการแคชดังนั้นสิ่งสำคัญคือต้องสามารถปิดใช้งานแคชระดับที่สองได้

แคชระดับที่สองของไฮเบอร์เนตถูกตั้งค่าในสองขั้นตอน ขั้นแรกคุณต้องตัดสินใจว่าจะใช้กลยุทธ์ใดพร้อมกัน หลังจากนั้นคุณกำหนดค่าการหมดอายุแคชและแอ็ตทริบิวต์แคชฟิสิคัลโดยใช้ผู้ให้บริการแคช

กลยุทธ์การทำงานพร้อมกัน

กลยุทธ์การทำงานพร้อมกันเป็นสื่อกลางซึ่งมีหน้าที่จัดเก็บรายการข้อมูลในแคชและดึงข้อมูลเหล่านั้นจากแคช หากคุณกำลังจะเปิดใช้งานแคชระดับที่สองคุณจะต้องตัดสินใจสำหรับแต่ละคลาสและคอลเล็กชันแบบถาวรซึ่งจะใช้กลยุทธ์แคชพร้อมกันที่จะใช้

  • Transactional - ใช้กลยุทธ์นี้สำหรับข้อมูลที่อ่านเป็นส่วนใหญ่ซึ่งเป็นสิ่งสำคัญในการป้องกันไม่ให้ข้อมูลเก่าในธุรกรรมพร้อมกันในกรณีที่ไม่ค่อยเกิดขึ้นกับการอัปเดต

  • Read-write - ใช้กลยุทธ์นี้อีกครั้งสำหรับข้อมูลที่อ่านเป็นส่วนใหญ่ซึ่งมีความสำคัญอย่างยิ่งในการป้องกันข้อมูลเก่าในธุรกรรมพร้อมกันในกรณีที่ไม่ค่อยเกิดขึ้นกับการอัปเดต

  • Nonstrict-read-write- กลยุทธ์นี้ไม่รับประกันความสอดคล้องระหว่างแคชและฐานข้อมูล ใช้กลยุทธ์นี้หากข้อมูลแทบจะไม่เคยเปลี่ยนแปลงและความเป็นไปได้เล็กน้อยที่ข้อมูลจะเก่าไม่ใช่เรื่องสำคัญ

  • Read-only- กลยุทธ์การทำงานพร้อมกันที่เหมาะสมกับข้อมูลซึ่งไม่เคยเปลี่ยนแปลง ใช้เพื่ออ้างอิงข้อมูลเท่านั้น

หากเราจะใช้การแคชระดับที่สองสำหรับไฟล์ Employee ให้เราเพิ่มองค์ประกอบการทำแผนที่ที่จำเป็นเพื่อบอกให้ Hibernate แคชอินสแตนซ์ของพนักงานโดยใช้กลยุทธ์การอ่าน - เขียน

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <cache usage = "read-write"/>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

แอ็ตทริบิวต์ use = "read-write" บอกให้ Hibernate ใช้กลยุทธ์การอ่าน - เขียนพร้อมกันสำหรับแคชที่กำหนด

ผู้ให้บริการแคช

ขั้นตอนต่อไปของคุณหลังจากพิจารณากลยุทธ์การทำงานพร้อมกันแล้วคุณจะใช้คลาสผู้สมัครแคชของคุณเพื่อเลือกผู้ให้บริการแคช ไฮเบอร์เนตบังคับให้คุณเลือกผู้ให้บริการแคชรายเดียวสำหรับแอปพลิเคชันทั้งหมด

ซีเนียร์ ชื่อแคชและคำอธิบาย
1

EHCache

สามารถแคชในหน่วยความจำหรือบนดิสก์และการแคชแบบคลัสเตอร์และรองรับแคชผลการสืบค้น Hibernate ที่เป็นทางเลือก

2

OSCache

รองรับการแคชไปยังหน่วยความจำและดิสก์ใน JVM เดียวพร้อมชุดนโยบายการหมดอายุและการสนับสนุนแคชแบบสอบถาม

3

warmCache

แคชคลัสเตอร์ตาม JGroups ใช้การทำให้เป็นโมฆะคลัสเตอร์ แต่ไม่รองรับแคชแบบสอบถามไฮเบอร์เนต

4

JBoss Cache

แคชคลัสเตอร์ที่จำลองแบบทรานแซคชันโดยสมบูรณ์ยังอิงตามไลบรารีมัลติคาสต์ JGroups สนับสนุนการจำลองแบบหรือการยกเลิกการสื่อสารแบบซิงโครนัสหรืออะซิงโครนัสและการล็อกในแง่ดีและแง่ร้าย รองรับแคชแบบสอบถามไฮเบอร์เนต

ผู้ให้บริการแคชทุกรายไม่สามารถใช้งานได้กับทุกกลยุทธ์ที่เกิดขึ้นพร้อมกัน เมทริกซ์ความเข้ากันได้ต่อไปนี้จะช่วยให้คุณเลือกชุดค่าผสมที่เหมาะสม

กลยุทธ์ / ผู้ให้บริการ อ่านเท่านั้น ไม่เข้มงวดอ่านเขียน อ่านเขียน การทำธุรกรรม
EHCache X X X  
OSCache X X X  
SwarmCache X X    
แคช JBoss X     X

คุณจะระบุผู้ให้บริการแคชในไฟล์คอนฟิกูเรชัน hibernate.cfg.xml เราเลือก EHCache เป็นผู้ให้บริการแคชระดับที่สองของเรา -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
   
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>
   
      <!-- Assume students is the database name -->
   
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
   
      <property name = "hibernate.connection.username">
         root
      </property>
   
      <property name = "hibernate.connection.password">
         root123
      </property>
   
      <property name = "hibernate.cache.provider_class">
         org.hibernate.cache.EhCacheProvider
      </property>
   
      <!-- List of XML mapping files -->
      <mapping resource = "Employee.hbm.xml"/>
   
   </session-factory>
</hibernate-configuration>

ตอนนี้คุณต้องระบุคุณสมบัติของพื้นที่แคช EHCache มีไฟล์กำหนดค่าของตัวเองehcache.xmlซึ่งควรอยู่ใน CLASSPATH ของแอปพลิเคชัน การกำหนดค่าแคชใน ehcache.xml สำหรับคลาส Employee อาจมีลักษณะดังนี้ -

<diskStore path="java.io.tmpdir"/>

<defaultCache
maxElementsInMemory = "1000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
/>

<cache name = "Employee"
maxElementsInMemory = "500"
eternal = "true"
timeToIdleSeconds = "0"
timeToLiveSeconds = "0"
overflowToDisk = "false"
/>

ตอนนี้เราได้เปิดใช้งานการแคชระดับที่สองสำหรับคลาสพนักงานและไฮเบอร์เนตแล้วตอนนี้เข้าสู่แคชระดับที่สองเมื่อใดก็ตามที่คุณไปที่พนักงานหรือเมื่อคุณโหลดพนักงานโดยใช้ตัวระบุ

คุณควรวิเคราะห์คลาสทั้งหมดของคุณและเลือกกลยุทธ์การแคชที่เหมาะสมสำหรับแต่ละคลาส ในบางครั้งการแคชระดับที่สองอาจลดระดับประสิทธิภาพของแอปพลิเคชัน ดังนั้นขอแนะนำให้เปรียบเทียบแอปพลิเคชันของคุณก่อนโดยไม่ต้องเปิดใช้งานการแคชและเปิดใช้งานการแคชที่เหมาะสมและตรวจสอบประสิทธิภาพในภายหลัง หากการแคชไม่ได้ปรับปรุงประสิทธิภาพของระบบก็จะไม่มีจุดใดในการเปิดใช้งานการแคชประเภทใด ๆ

แคชระดับการสืบค้น

ในการใช้แคชแบบสอบถามก่อนอื่นคุณต้องเปิดใช้งานโดยใช้ไฟล์ hibernate.cache.use_query_cache="true"คุณสมบัติในไฟล์คอนฟิกูเรชัน เมื่อตั้งค่าคุณสมบัตินี้เป็นจริงคุณทำให้ไฮเบอร์เนตสร้างแคชที่จำเป็นในหน่วยความจำเพื่อเก็บคิวรีและชุดตัวระบุ

ถัดไปในการใช้แคชแบบสอบถามคุณใช้เมธอด setCacheable (บูลีน) ของคลาส Query ตัวอย่างเช่น -

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();

Hibernate ยังรองรับการรองรับแคชแบบละเอียดมากผ่านแนวคิดของพื้นที่แคช พื้นที่แคชเป็นส่วนหนึ่งของแคชที่กำหนดชื่อ

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();

รหัสนี้ใช้วิธีการบอกให้ Hibernate จัดเก็บและค้นหาคำค้นหาในพื้นที่แคชของพนักงาน

พิจารณาสถานการณ์เมื่อคุณต้องการอัปโหลดบันทึกจำนวนมากไปยังฐานข้อมูลของคุณโดยใช้ไฮเบอร์เนต ต่อไปนี้เป็นข้อมูลโค้ดเพื่อให้บรรลุสิ่งนี้โดยใช้ไฮเบอร์เนต -

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
   Employee employee = new Employee(.....);
   session.save(employee);
}
tx.commit();
session.close();

ตามค่าเริ่มต้น Hibernate จะแคชวัตถุที่มีอยู่ทั้งหมดในแคชระดับเซสชันและท้ายที่สุดแอปพลิเคชันของคุณจะตกอยู่ใน OutOfMemoryExceptionที่ไหนสักแห่งแถวที่ 50,000 คุณสามารถแก้ไขปัญหานี้ได้หากคุณใช้batch processing ด้วยไฮเบอร์เนต

ในการใช้คุณสมบัติการประมวลผลชุดงานให้ตั้งค่าก่อน hibernate.jdbc.batch_sizeเป็นขนาดแบทช์เป็นตัวเลขที่ 20 หรือ 50 ขึ้นอยู่กับขนาดวัตถุ สิ่งนี้จะบอกคอนเทนเนอร์ไฮเบอร์เนตว่าทุกแถว X จะถูกแทรกเป็นแบตช์ ในการติดตั้งโค้ดของคุณเราจำเป็นต้องทำการปรับเปลี่ยนเล็กน้อยดังนี้ -

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
   Employee employee = new Employee(.....);
   session.save(employee);
   if( i % 50 == 0 ) { // Same as the JDBC batch size
      //flush a batch of inserts and release memory:
      session.flush();
      session.clear();
   }
}
tx.commit();
session.close();

โค้ดด้านบนจะทำงานได้ดีสำหรับการดำเนินการ INSERT แต่ถ้าคุณยินดีที่จะทำการ UPDATE คุณสามารถทำได้โดยใช้รหัสต่อไปนี้ -

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

ScrollableResults employeeCursor = session.createQuery("FROM EMPLOYEE").scroll();
int count = 0;

while ( employeeCursor.next() ) {
   Employee employee = (Employee) employeeCursor.get(0);
   employee.updateEmployee();
   seession.update(employee); 
   if ( ++count % 50 == 0 ) {
      session.flush();
      session.clear();
   }
}
tx.commit();
session.close();

ตัวอย่างการประมวลผลแบทช์

ให้เราแก้ไขไฟล์คอนฟิกเพื่อเพิ่ม hibernate.jdbc.batch_size คุณสมบัติ -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
   
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>

      <!-- Assume students is the database name -->
   
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
   
      <property name = "hibernate.connection.username">
         root
      </property>
   
      <property name = "hibernate.connection.password">
         root123
      </property>
   
      <property name = "hibernate.jdbc.batch_size">
         50
      </property>

      <!-- List of XML mapping files -->
      <mapping resource = "Employee.hbm.xml"/>

   </session-factory>
</hibernate-configuration>

พิจารณาระดับพนักงาน POJO ต่อไปนี้ -

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

ให้เราสร้างตาราง EMPLOYEE ต่อไปนี้เพื่อจัดเก็บวัตถุพนักงาน -

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

ต่อไปนี้จะเป็นไฟล์การแมปเพื่อแมปวัตถุพนักงานกับตารางพนักงาน -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

สุดท้ายเราจะสร้างคลาสแอปพลิเคชันของเราด้วยเมธอด main () เพื่อเรียกใช้แอปพลิเคชันที่เราจะใช้ flush() และ clear() วิธีการที่มีอยู่ในวัตถุเซสชันเพื่อให้ Hibernate เขียนบันทึกเหล่านี้ลงในฐานข้อมูลแทนการแคชไว้ในหน่วยความจำ

import java.util.*; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      ManageEmployee ME = new ManageEmployee();

      /* Add employee records in batches */
      ME.addEmployees( );
   }
   
   /* Method to create employee records in batches */
   public void addEmployees( ){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         for ( int i=0; i<100000; i++ ) {
            String fname = "First Name " + i;
            String lname = "Last Name " + i;
            Integer salary = i;
            Employee employee = new Employee(fname, lname, salary);
            session.save(employee);
         	if( i % 50 == 0 ) {
               session.flush();
               session.clear();
            }
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return ;
   }
}

การรวบรวมและการดำเนินการ

นี่คือขั้นตอนในการรวบรวมและเรียกใช้แอปพลิเคชันที่กล่าวถึงข้างต้น ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่า PATH และ CLASSPATH อย่างเหมาะสมก่อนดำเนินการรวบรวมและดำเนินการ

  • สร้างไฟล์กำหนดค่า hibernate.cfg.xml ตามที่อธิบายไว้ข้างต้น

  • สร้างไฟล์การแมป Employee.hbm.xml ดังที่แสดงด้านบน

  • สร้างไฟล์ซอร์ส Employee.java ตามที่แสดงด้านบนและคอมไพล์

  • สร้างไฟล์ต้นฉบับ ManageEmployee.java ตามที่แสดงด้านบนและคอมไพล์

  • เรียกใช้ไบนารี ManageEmployee เพื่อรันโปรแกรมซึ่งจะสร้าง 100000 เรกคอร์ดในตาราง EMPLOYEE

ดังที่คุณได้เรียนรู้ว่าในโหมดไฮเบอร์เนตวัตถุจะถูกสร้างขึ้นและคงอยู่ เมื่อวัตถุถูกเปลี่ยนแปลงแล้วจะต้องบันทึกกลับไปที่ฐานข้อมูล กระบวนการนี้จะดำเนินต่อไปจนกว่าจะถึงเวลาที่ต้องการวัตถุครั้งต่อไปและจะโหลดจากที่เก็บถาวร

ดังนั้นวัตถุจึงผ่านขั้นตอนต่างๆในวงจรชีวิตและ Interceptor Interfaceมีวิธีการซึ่งสามารถเรียกได้ในขั้นตอนต่างๆเพื่อดำเนินการบางอย่างที่จำเป็น วิธีการเหล่านี้เป็นการเรียกกลับจากเซสชันไปยังแอ็พพลิเคชันซึ่งอนุญาตให้แอปพลิเคชันตรวจสอบและ / หรือจัดการคุณสมบัติของอ็อบเจ็กต์ถาวรก่อนที่จะถูกบันทึกอัพเดตลบหรือโหลด ต่อไปนี้เป็นรายการวิธีการทั้งหมดที่มีอยู่ในอินเทอร์เฟซ Interceptor -

ซีเนียร์ วิธีการและคำอธิบาย
1

findDirty()

วิธีนี้เรียกว่าเมื่อไฟล์ flush() เมธอดถูกเรียกบนวัตถุเซสชัน

2

instantiate()

เมธอดนี้เรียกว่าเมื่อคลาสที่ยังคงอยู่ถูกสร้างอินสแตนซ์

3

isUnsaved()

วิธีนี้เรียกว่าเมื่อวัตถุถูกส่งไปยังไฟล์ saveOrUpdate() วิธี/

4

onDelete()

วิธีนี้เรียกก่อนที่วัตถุจะถูกลบ

5

onFlushDirty()

วิธีนี้เรียกว่าเมื่อ Hibernate ตรวจพบว่าวัตถุสกปรก (เช่นมีการเปลี่ยนแปลง) ในระหว่างการดำเนินการอัพเดตแบบล้าง

6

onLoad()

วิธีนี้เรียกว่าก่อนที่วัตถุจะเริ่มต้น

7

onSave()

วิธีนี้เรียกก่อนที่จะบันทึกวัตถุ

8

postFlush()

เมธอดนี้เรียกว่าหลังจากเกิดฟลัชและอ็อบเจ็กต์ได้รับการอัพเดตในหน่วยความจำ

9

preFlush()

วิธีนี้เรียกว่าก่อนการล้าง

Hibernate Interceptor ช่วยให้เราสามารถควบคุมได้ทั้งหมดว่าวัตถุจะมีลักษณะอย่างไรกับทั้งแอปพลิเคชันและฐานข้อมูล

วิธีใช้ Interceptors?

ในการสร้างเครื่องสกัดกั้นคุณสามารถใช้งานได้ Interceptor ชั้นเรียนโดยตรงหรือขยาย EmptyInterceptorชั้นเรียน. ต่อไปนี้เป็นขั้นตอนง่ายๆในการใช้ฟังก์ชัน Hibernate Interceptor

สร้าง Interceptors

เราจะขยาย EmptyInterceptor ในตัวอย่างของเราโดยที่เมธอดของ Interceptor จะถูกเรียกโดยอัตโนมัติเมื่อ Employeeสร้างและอัปเดตวัตถุ คุณสามารถใช้วิธีการเพิ่มเติมตามความต้องการของคุณ

import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;

import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

public class MyInterceptor extends EmptyInterceptor {
   private int updates;
   private int creates;
   private int loads;

   public void onDelete(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
       // do nothing
   }

   // This method is called when Employee object gets updated.
   public boolean onFlushDirty(Object entity, Serializable id,
      Object[] currentState, Object[] previousState, String[] propertyNames,
      Type[] types) {
         if ( entity instanceof Employee ) {
            System.out.println("Update Operation");
            return true; 
         }
         return false;
   }
	
   public boolean onLoad(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
         // do nothing
         return true;
   }
   
   // This method is called when Employee object gets created.
   public boolean onSave(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
         if ( entity instanceof Employee ) {
            System.out.println("Create Operation");
            return true; 
         }
         return false;
   }
   
   //called before commit into database
   public void preFlush(Iterator iterator) {
      System.out.println("preFlush");
   }
   
   //called after committed into database
   public void postFlush(Iterator iterator) {
      System.out.println("postFlush");
   }
}

สร้างคลาส POJO

ตอนนี้ให้เราปรับเปลี่ยนตัวอย่างแรกของเราเล็กน้อยที่เราใช้ตาราง EMPLOYEE และคลาสพนักงานเพื่อเล่นด้วย -

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

สร้างตารางฐานข้อมูล

ขั้นตอนที่สองคือการสร้างตารางในฐานข้อมูลของคุณ จะมีตารางหนึ่งตารางที่สอดคล้องกับแต่ละวัตถุคุณยินดีที่จะให้ความคงอยู่ พิจารณาวัตถุที่อธิบายข้างต้นจำเป็นต้องจัดเก็บและเรียกดูในตาราง RDBMS ต่อไปนี้ -

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

สร้างไฟล์คอนฟิกูเรชันการแมป

ขั้นตอนนี้คือการสร้างไฟล์การแมปที่สั่งให้ไฮเบอร์เนต - วิธีการแมปคลาสหรือคลาสที่กำหนดไว้กับตารางฐานข้อมูล

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

สร้างคลาสแอปพลิเคชัน

สุดท้ายเราจะสร้างคลาสแอปพลิเคชันของเราด้วยเมธอด main () เพื่อเรียกใช้แอปพลิเคชัน ที่นี่ควรสังเกตว่าในขณะที่สร้างวัตถุเซสชันเราใช้คลาส Interceptor ของเราเป็นอาร์กิวเมนต์

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }

      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 10000);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down new list of the employees */
      ME.listEmployees();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }
   
   /* Method to  READ all the employees */
   public void listEmployees( ){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").list(); 
         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to UPDATE salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
		 session.update(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to DELETE an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

การรวบรวมและการดำเนินการ

นี่คือขั้นตอนในการรวบรวมและเรียกใช้แอปพลิเคชันที่กล่าวถึงข้างต้น ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่า PATH และ CLASSPATH อย่างเหมาะสมก่อนดำเนินการรวบรวมและดำเนินการ

  • สร้างไฟล์คอนฟิกูเรชัน hibernate.cfg.xml ตามที่อธิบายไว้ในบทการกำหนดค่า

  • สร้างไฟล์การแมป Employee.hbm.xml ดังที่แสดงด้านบน

  • สร้างไฟล์ซอร์ส Employee.java ตามที่แสดงด้านบนและคอมไพล์

  • สร้างไฟล์ซอร์ส MyInterceptor.java ตามที่แสดงด้านบนและคอมไพล์

  • สร้างไฟล์ต้นฉบับ ManageEmployee.java ตามที่แสดงด้านบนและคอมไพล์

  • ดำเนินการไบนารี ManageEmployee เพื่อรันโปรแกรม

คุณจะได้รับผลลัพธ์ดังต่อไปนี้และบันทึกจะถูกสร้างขึ้นในตาราง EMPLOYEE

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
First Name: Zara  Last Name: Ali  Salary: 1000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
preFlush
postFlush
preFlush
Update Operation
postFlush
preFlush
postFlush
First Name: Zara  Last Name: Ali  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
preFlush
postFlush

หากคุณตรวจสอบตารางพนักงานของคุณควรมีบันทึกดังต่อไปนี้ -

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara       | Ali       |   5000 |
| 31 | John       | Paul      |  10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec
mysql>