Hibernate และ Database Lock 1. ทำไมต้องใช้ล็อค?
หากต้องการทราบว่าทำไมกลไกการล็อคจึงต้องเข้าใจแนวคิดของการทำธุรกรรมก่อน
การทำธุรกรรมเป็นชุดของการดำเนินการที่เกี่ยวข้องในฐานข้อมูลและจะต้องมีลักษณะของกรด:
ฐานข้อมูลเชิงสัมพันธ์ที่ใช้กันทั่วไปของเรา RDBMS ใช้คุณสมบัติของธุรกรรมเหล่านี้ ในหมู่พวกเขาอะตอม
ความสอดคล้องและการคงอยู่ได้รับการรับประกันโดยการบันทึก การแยกนั้นเกิดขึ้นได้จากกลไกการล็อคที่เรากังวลเกี่ยวกับวันนี้ซึ่งเป็นสาเหตุที่เราต้องการกลไกการล็อค
หากไม่มีการล็อคและไม่มีการควบคุมการแยกผลที่ตามมาอาจเกิดอะไรขึ้น?
มาดูตัวอย่างของไฮเบอร์เนต สองเธรดเริ่มต้นการทำธุรกรรมสองรายการตามลำดับ ข้อมูลแถวเดียวกันในตาราง tb_account คือ col_id = 1
แพ็คเกจ com.cdai.orm.hibernate.annotation; นำเข้า java.io.serializable; นำเข้า Javax.persistence.column; นำเข้า Javax.persistence.entity; นำเข้า Javax.persistence.id; นำเข้า Javax.persistence.Table; @ENTITY @Table (name = "tb_account") บัญชีชั้นเรียนสาธารณะใช้ serializable {ส่วนตัวคงที่สุดท้าย Long SerialVersionUID = 5018821760412231859L; @id @column (name = "col_id") ID ยาวส่วนตัว; @column (name = "col_balance") สมดุลยาวส่วนตัว; บัญชีสาธารณะ () {} บัญชีสาธารณะ (ID ยาว, ยอดคงเหลือยาว) {this.id = id; this.balance = Balance; } สาธารณะ Long getId () {return id; } โมฆะสาธารณะ setId (Long id) {this.id = id; } การ getBalance สาธารณะยาว () {ยอดคงเหลือคืน; } โมฆะสาธารณะ setBalance (สมดุลยาว) {this.balance = สมดุล; } @Override สตริงสาธารณะ toString () {return "บัญชี [id =" + id + ", balance =" + balance + "]"; - แพ็คเกจ com.cdai.orm.hibernate.transaction; นำเข้า org.hibernate.session; นำเข้า org.hibernate.sessionfactory; นำเข้า org.hibernate.transaction; นำเข้า org.hibernate.cfg.annotationConfiguration; นำเข้า com.cdai.orm.hibernate.annotation.account; ชั้นเรียนสาธารณะ DirtyRead {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {ขั้นสุดท้าย sessionFactory sessionFactory = new AnnotationConfiguration () addfile ("hibernate/hibernate.cfg.xml") กำหนดค่า () addpackage ("com.cdai.orm.hibernate.annotation") AddannotatedClass (บัญชี. class) BuildSessionFactory (); เธรด t1 = เธรดใหม่ () {@Override โมฆะสาธารณะเรียกใช้ () {เซสชันเซสชัน 1 = sessionfactory.opensession (); ธุรกรรม TX1 = NULL; ลอง {tx1 = session1.beginTransaction (); System.out.println ("T1 - เริ่มต้น trasaction"); Thread.sleep (500); บัญชีบัญชี = (บัญชี) session1.get (บัญชี. คลาสยาวใหม่ (1)); System.out.println ("t1 - balance =" + account.getBalance ()); Thread.sleep (500); Account.setBalance (Account.getBalance () + 100); System.out.println ("T1 - เปลี่ยนยอดคงเหลือ:" + account.getBalance ()); tx1.Commit (); System.out.println ("T1 - กระทำการทำธุรกรรม"); Thread.sleep (500); } catch (exception e) {e.printstacktrace (); if (tx1! = null) tx1.rollback (); } ในที่สุด {session1.close (); - // 3.RUN การทำธุรกรรม 2 เธรด t2 = เธรดใหม่ () {@Override โมฆะสาธารณะเรียกใช้ () {เซสชัน Session2 = SessionFactory.opensession (); ธุรกรรม tx2 = null; ลอง {tx2 = session2.beginTransaction (); System.out.println ("T2 - เริ่มต้น trasaction"); Thread.sleep (500); บัญชีบัญชี = (บัญชี) session2.get (บัญชี. class, ใหม่ยาว (1)); System.out.println ("t2 - balance =" + account.getBalance ()); Thread.sleep (500); Account.setBalance (Account.getBalance () - 100); System.out.println ("T2 - เปลี่ยนยอดคงเหลือ:" + account.getBalance ()); tx2.Commit (); System.out.println ("T2 - ทำธุรกรรม"); Thread.sleep (500); } catch (exception e) {e.printstacktrace (); if (tx2! = null) tx2.rollback (); } ในที่สุด {session2.close (); - t1.start (); t2.start (); ในขณะที่ (t1.isalive () || t2.isalive ()) {ลอง {thread.sleep (2000l); } catch (interruptedException e) {}} system.out.println ("ทั้ง T1 และ T2 ตายแล้ว"); SessionFactory.close (); - ธุรกรรม 1 ลด Col_balance ลง 100 ในขณะที่ธุรกรรม 2 ลดลง 100 ผลลัพธ์สุดท้ายอาจเป็น 0 หรือ 200 และการอัปเดตการทำธุรกรรม 1 หรือ 2 อาจหายไป เอาต์พุตบันทึกยังยืนยันสิ่งนี้ธุรกรรม 1 และ 2
บันทึกข้ามการพิมพ์
T1 - เริ่มต้น trasactiont2 - เริ่ม trasactionhibernate: เลือก account0_.col_id เป็น col1_0_0_, account0_.col_balance เป็น col2_0_0_ จาก tb_account account0_ โดยที่บัญชี 0_.col_id =? tb_account accountion0_ โดยที่บัญชี 0_.col_id =? t1 - ยอดคงเหลือ = 100t2 - ยอดคงเหลือ = 100t2 - เปลี่ยนยอดคงเหลือ: 0t1 - เปลี่ยนยอดคงเหลือ: 200hibernate: อัปเดต tb_account set col_balance =? ที่ col_id =? hibernate: อัปเดต tb_account set col_balance =? โดยที่ col_id =? t1 - กระทำการทำธุรกรรม T2 - กระทำการทำธุรกรรมทั้ง T1 และ T2 ตายแล้ว
จะเห็นได้ว่าการแยกเป็นเรื่องที่ต้องพิจารณาอย่างรอบคอบและจำเป็นต้องเข้าใจล็อค
2. ล็อคมีกี่ประเภท?
คนทั่วไปคือล็อคที่ใช้ร่วมกันอัปเดตล็อคและล็อคพิเศษ
1. การล็อคที่ใช้ร่วมกัน: ใช้สำหรับการอ่านการดำเนินการข้อมูลทำให้สามารถอ่านธุรกรรมอื่น ๆ พร้อมกันได้ เมื่อธุรกรรมดำเนินการคำสั่ง SELECT
ฐานข้อมูลจะกำหนดล็อคที่ใช้ร่วมกันโดยอัตโนมัติไปยังธุรกรรมเพื่อล็อคข้อมูลการอ่าน
2. ล็อคพิเศษ: ใช้เพื่อแก้ไขข้อมูลธุรกรรมอื่น ๆ ไม่สามารถอ่านหรือแก้ไขได้ เมื่อธุรกรรมดำเนินการแทรก
เมื่ออัปเดตและลบข้อมูลฐานข้อมูลจะได้รับการจัดสรรโดยอัตโนมัติ
3. การปรับปรุงล็อค: ใช้เพื่อหลีกเลี่ยงการหยุดชะงักที่เกิดจากการล็อคที่ใช้ร่วมกันในระหว่างการดำเนินการอัปเดตเช่นธุรกรรม 1 และ 2 ล็อคที่ใช้ร่วมกันในเวลาเดียวกันและรอรับล็อคพิเศษ เมื่อทำการอัปเดตการทำธุรกรรมจะได้รับการล็อคการอัปเดตก่อนจากนั้นอัพเกรดล็อคการอัปเดตเป็นล็อคแบบเอกสิทธิ์เฉพาะบุคคลจึงหลีกเลี่ยงการหยุดชะงัก
นอกจากนี้ล็อคเหล่านี้ทั้งหมดสามารถนำไปใช้กับวัตถุที่แตกต่างกันในฐานข้อมูลเช่นล็อคเหล่านี้สามารถมีความละเอียดที่แตกต่างกัน
เช่นล็อคระดับฐานข้อมูลล็อคระดับตารางการล็อคระดับหน้าการล็อคระดับคีย์และล็อคระดับแถว
ดังนั้นจึงมีล็อคหลายประเภท มันยากเกินไปที่จะเชี่ยวชาญอย่างเต็มที่และใช้ล็อคจำนวนมากอย่างยืดหยุ่น เราไม่ใช่ DBA
จะทำอย่างไร? โชคดีที่กลไกการล็อคนั้นโปร่งใสสำหรับผู้ใช้ทั่วไป ฐานข้อมูลจะเพิ่มล็อคที่เหมาะสมโดยอัตโนมัติและอัพเกรดและลดระดับล็อคต่างๆโดยอัตโนมัติในเวลาที่เหมาะสม มันรอบคอบมาก! สิ่งที่เราต้องทำคือเรียนรู้ที่จะกำหนดระดับการแยกตามความต้องการทางธุรกิจที่แตกต่างกัน
3. จะตั้งค่าระดับการแยกได้อย่างไร?
โดยทั่วไปแล้วระบบฐานข้อมูลมีระดับการแยกธุรกรรมสี่ระดับเพื่อให้ผู้ใช้เลือก:
1.Serializable: เมื่อสองธุรกรรมจัดการข้อมูลเดียวกันในเวลาเดียวกันธุรกรรม 2 สามารถหยุดและรอได้เท่านั้น
2. อ่านซ้ำ (ทำซ้ำได้): ธุรกรรม 1 สามารถดูข้อมูลที่แทรกใหม่จากธุรกรรม 2 และไม่เห็นการอัปเดตข้อมูลที่มีอยู่
3. อ่านความมุ่งมั่น (อ่านข้อมูลที่มุ่งมั่น): ธุรกรรม 1 สามารถดูข้อมูลที่แทรกและอัปเดตใหม่จากธุรกรรม 2
4. อ่าน uncommitted (อ่านข้อมูลที่ไม่มีข้อผูกมัด): ธุรกรรมที่ 1 สามารถเห็นการแทรกและอัปเดตข้อมูลที่ธุรกรรม 2 ไม่ได้กระทำ
4. ล็อคในแอปพลิเคชัน
เมื่อฐานข้อมูลใช้ระดับการแยกคณะกรรมการการอ่านล็อคในแง่ร้ายหรือล็อคในแง่ดีสามารถใช้ในแอปพลิเคชัน
1. การล็อคในแง่ร้าย: สมมติว่าข้อมูลของการดำเนินการธุรกรรมในปัจจุบันจะมีการเข้าถึงธุรกรรมอื่น ๆ อย่างแน่นอนดังนั้นระบุในแง่ร้ายว่าการล็อคแบบพิเศษถูกใช้ในแอปพลิเคชันเพื่อล็อคแหล่งข้อมูล สนับสนุนแบบฟอร์มต่อไปนี้ใน MySQL และ Oracle:
เลือก ... สำหรับการอัปเดต
ให้ Select ใช้ล็อคล็อคแบบพิเศษอย่างชัดเจนเพื่อล็อคเร็กคอร์ดของแบบสอบถาม สำหรับการทำธุรกรรมอื่น ๆ เพื่อสอบถามอัปเดตหรือลบข้อมูลที่ล็อคเหล่านี้พวกเขาจะต้องรอจนกว่าการทำธุรกรรมจะสิ้นสุดลง
ในไฮเบอร์เนตคุณสามารถผ่าน LockMode.Upgrade เมื่อโหลดเพื่อนำการล็อคในแง่ร้ายมาใช้ แก้ไขตัวอย่างก่อนหน้า
ที่ GET Method Calls of Transactions 1 และ 2 พารามิเตอร์ LockMode เพิ่มเติมจะถูกส่งผ่านตามที่สามารถเห็นได้จากบันทึกการทำธุรกรรม 1 และ 2
มันไม่ได้ดำเนินการข้ามการทำธุรกรรม 2 อีกต่อไปสามารถรอการทำธุรกรรม 1 ให้เสร็จสิ้นก่อนที่จะอ่านข้อมูลดังนั้นค่า col_balance สุดท้ายถูกต้อง 100
แพ็คเกจ com.cdai.orm.hibernate.transaction; นำเข้า org.hibernate.lockmode; นำเข้า org.hibernate.session; นำเข้า org.hibernate.sessionfactory; นำเข้า org.hibernate.transaction; นำเข้า com.cdai.orm.hibernate.annotation.account; นำเข้า com.cdai.orm.hibernate.annotation.annotationhibernate; ชั้นเรียนสาธารณะ UPGRADELOCK {@SuppressWarnings ("Deprecation") โมฆะคงที่สาธารณะหลัก (String [] args) {ขั้นสุดท้าย sessionFactory sessionFactory = AnnotationHiberNate.CreateSessionFactory (); // รันธุรกรรม 1 เธรด t1 = เธรดใหม่ () {@Override โมฆะสาธารณะเรียกใช้ () {เซสชันเซสชัน 1 = sessionFactory.opensession (); ธุรกรรม TX1 = NULL; ลอง {tx1 = session1.beginTransaction (); System.out.println ("T1 - เริ่มต้น trasaction"); Thread.sleep (500); บัญชีบัญชี = (บัญชี) session1.get (concent.class, Long ใหม่ (1), lockmode.upgrade); System.out.println ("t1 - balance =" + account.getBalance ()); Thread.sleep (500); Account.setBalance (Account.getBalance () + 100); System.out.println ("T1 - เปลี่ยนยอดคงเหลือ:" + account.getBalance ()); tx1.Commit (); System.out.println ("T1 - กระทำการทำธุรกรรม"); Thread.sleep (500); } catch (exception e) {e.printstacktrace (); if (tx1! = null) tx1.rollback (); } ในที่สุด {session1.close (); - // รันธุรกรรม 2 เธรด t2 = เธรดใหม่ () {@Override โมฆะสาธารณะเรียกใช้ () {เซสชันเซสชัน 2 = sessionFactory.opensession (); ธุรกรรม tx2 = null; ลอง {tx2 = session2.beginTransaction (); System.out.println ("T2 - เริ่มต้น trasaction"); Thread.sleep (500); บัญชีบัญชี = (บัญชี) session2.get (บัญชี. class, Long ใหม่ (1), lockmode.upgrade); System.out.println ("t2 - balance =" + account.getBalance ()); Thread.sleep (500); Account.setBalance (Account.getBalance () - 100); System.out.println ("T2 - เปลี่ยนยอดคงเหลือ:" + account.getBalance ()); tx2.Commit (); System.out.println ("T2 - ทำธุรกรรม"); Thread.sleep (500); } catch (exception e) {e.printstacktrace (); if (tx2! = null) tx2.rollback (); } ในที่สุด {session2.close (); - t1.start (); t2.start (); ในขณะที่ (t1.isalive () || t2.isalive ()) {ลอง {thread.sleep (2000l); } catch (interruptedException e) {}} system.out.println ("ทั้ง T1 และ T2 ตายแล้ว"); SessionFactory.close (); -T1 - เริ่มต้น trasactiont2 - เริ่ม trasactionhibernate: เลือก account0_.col_id เป็น col1_0_0_, account0_.col_balance เป็น col2_0_0_ จาก tb_account accountion0_ ด้วย (updlock, rowlock) col2_0_0_ จาก tb_account accountion0_ ด้วย (updlock, rowlock) โดยที่บัญชี 0_.col_id =? t2 - ยอดคงเหลือ = 100t2 - เปลี่ยนยอดคงเหลือ: 0hibernate: อัปเดต tb_account set col_balance =? โดยที่ col_id =? t2 - comment transactiont1 - balance = 0t1 - เปลี่ยนยอดคงเหลือ: 100HiberNate: อัปเดต tb_account set col_balance =? ที่ col_id =? t1 - ทำธุรกรรมทั้งสองและ t2 ตายแล้ว
Hibernate ดำเนินการ SQL สำหรับ SQLServer 2005:
การคัดลอกรหัสมีดังนี้:
เลือก account0_.col_id เป็น col1_0_0_, account0_.col_balance เป็น col2_0_0_ จาก tb_account accountion0_ ด้วย (updlock, rowlock) โดยที่บัญชี 0_.col_id =?
2. การล็อคในแง่ดี: สมมติว่าข้อมูลของการดำเนินการธุรกรรมในปัจจุบันจะไม่สามารถเข้าถึงได้ในเวลาเดียวกันโดยการทำธุรกรรมอื่น ๆ ดังนั้นระดับการแยกของฐานข้อมูลจึงขึ้นอยู่กับฐานข้อมูลอย่างสมบูรณ์เพื่อจัดการงานของล็อคโดยอัตโนมัติ นำการควบคุมเวอร์ชันมาใช้ในแอปพลิเคชันเพื่อหลีกเลี่ยงปัญหาพร้อมกันที่อาจเกิดขึ้นที่ความน่าจะเป็นต่ำ
ในไฮเบอร์เนตให้ใช้คำอธิบายประกอบเวอร์ชันเพื่อกำหนดฟิลด์หมายเลขเวอร์ชัน
แทนที่วัตถุบัญชีใน DirtyLock ด้วย accountVersion และรหัสอื่น ๆ ยังคงไม่เปลี่ยนแปลงและมีข้อยกเว้นเกิดขึ้นเมื่อมีการดำเนินการเกิดขึ้น
แพ็คเกจ com.cdai.orm.hibernate.transaction; นำเข้า Javax.persistence.column; นำเข้า Javax.persistence.entity; นำเข้า Javax.persistence.id; นำเข้า Javax.persistence.Table; นำเข้า javax.persistence.version; @ENTITY @Table (name = "tb_account_version") บัญชีสาธารณะบัญชี {@id @column (name = "col_id") ID ยาวส่วนตัว; @column (name = "col_balance") สมดุลยาวส่วนตัว; @Version @column (name = "col_version") เวอร์ชัน int ส่วนตัว; บัญชีสาธารณะ () {} บัญชีสาธารณะ (ID ยาว, ยอดคงเหลือยาว) {this.id = id; this.balance = Balance; } สาธารณะ Long getId () {return id; } โมฆะสาธารณะ setId (Long id) {this.id = id; } การ getBalance สาธารณะยาว () {ยอดคงเหลือคืน; } โมฆะสาธารณะ setBalance (สมดุลยาว) {this.balance = สมดุล; } public int getVersion () {เวอร์ชันส่งคืน; } โมฆะสาธารณะ setVersion (int เวอร์ชัน) {this.version = เวอร์ชัน; -บันทึกมีดังนี้:
T1 - เริ่มต้น trasactiont2 - เริ่ม trasactionhibernate: เลือก accountver0_.col_id เป็น col1_0_0_, accountver0_.col_balance เป็น col2_0_0_, accountver0_.col_version เป็น col3_0_0_ จาก tb_account_version col1_0_0_, accountver0_.col_balance เป็น col2_0_0_, accountver0_.col_version เป็น col3_0_0_ จาก tb_account_version accountver0_ ที่บัญชี 0_.col_id =? t1 - ยอดคงเหลือ = 1000t2 - สมดุล = 1000t1 col_balance = ?, col_version =? col_id =? และ col_version =? hibernate: อัปเดต tb_account_version set col_balance =?, col_version =? col_id =? และ col_version =? t1 - กระทำการทำธุรกรรม 2264 [เธรด -2] ข้อผิดพลาด org.hibernate.event.def.abstractflushingeventListener - ไม่สามารถซิงโครไนซ์สถานะฐานข้อมูลกับ sessionorg.hibernate.staleObjectStateException: ROW ได้รับการปรับปรุง [com.cdai.orm.hibernate.Transaction.AccountVersion#1] ที่ org.hibernate.persister.entity.abstractentitypersister.check (Abstractentitypersister.java:1934) ที่ org.hibernate.persister.entity org.hibernate.persister.entity.abstractentitypersister.updateorinsert (Abstractentitypersister.java:2478) ที่ org.hibernate.persister.entity.abstractentitypersister.update org.hibernate.action.entityUpdateAction.execute (entityUpdateAction.java:114) ที่ org.hibernate.engine.actionqueue.execute (actionqueue.java:268) ที่ org.hibernate.engine.actionqueue org.hibernate.engine.actionqueue.executeactions (actionqueue.java:180) ที่ org.hibernate.event.def.abstractflushingeventlistener.performexecutions (AbstractflushingeventListener.java:321) org.hibernate.event.def.defaultflusheventlistener.onflush (defaultflusheventlistener.java:51) ที่ org.hibernate.impl.sessionimpl.flush org.hibernate.transaction.jdbctransaction.Commit (jdbctransaction.java:137) ที่ com.cdai.ornat.transaction.vava.vava:137 $ 2.run
เนื่องจากการล็อคในแง่ดีออกจากการแยกธุรกรรมไปยังฐานข้อมูลสำหรับการควบคุมการทำธุรกรรม 1 และ 2 เรียกใช้การวิ่งข้ามการทำธุรกรรม 1 ได้สำเร็จและเปลี่ยน COL_VERSION เป็น 1 อย่างไรก็ตามเมื่อการทำธุรกรรม 2 ดำเนินการข้อมูลที่มี COL_VERSION ของ 0 ไม่สามารถพบได้อีกต่อไป
การเปรียบเทียบวิธีการสอบถามไฮเบอร์เนต
มีสามวิธีการสืบค้นหลักสำหรับไฮเบอร์เนต:
1.HQL (ภาษาคิวรีไฮเบอร์เนต)
มันคล้ายกับ SQL มากและรองรับคุณสมบัติเช่นการเพจ, การเชื่อมต่อ, การจัดกลุ่ม, ฟังก์ชั่นการรวมและคำถามย่อย
แต่ HQL นั้นมุ่งเน้นวัตถุไม่ใช่ตารางในฐานข้อมูลเชิงสัมพันธ์ เนื่องจากคำสั่งแบบสอบถามมุ่งเน้นไปที่วัตถุโดเมนการใช้ HQL สามารถได้รับประโยชน์ข้ามแพลตฟอร์ม โภชนาการ
มันจะช่วยให้เราแปลเป็นคำสั่ง SQL ที่แตกต่างกันโดยอัตโนมัติตามฐานข้อมูลที่แตกต่างกัน สิ่งนี้สะดวกมากในแอปพลิเคชันที่จำเป็นต้องสนับสนุนฐานข้อมูลหลายฐานข้อมูลหรือการย้ายฐานข้อมูล
แต่ในขณะที่ได้รับความสะดวกเนื่องจากคำสั่ง SQL ถูกสร้างขึ้นโดยไฮเบอร์เนตโดยอัตโนมัติสิ่งนี้ไม่เอื้อต่อการเพิ่มประสิทธิภาพประสิทธิภาพและการดีบักของคำสั่ง SQL เมื่อปริมาณข้อมูลมีขนาดใหญ่อาจมีปัญหาด้านประสิทธิภาพ
หากมีปัญหาก็ไม่สะดวกในการตรวจสอบและแก้ไขปัญหา
2.QBC/QBE (Query ตามเกณฑ์/ตัวอย่าง)
QBC/QBE ดำเนินการสืบค้นโดยการรวบรวมเงื่อนไขการสืบค้นหรือวัตถุเทมเพลต สิ่งนี้สะดวกสบายในแอปพลิเคชันที่ต้องการการสนับสนุนที่ยืดหยุ่นสำหรับการรวมกันของเงื่อนไขการสืบค้นฟรีจำนวนมาก ปัญหาเดียวกันก็คือเนื่องจากคำสั่งแบบสอบถามประกอบขึ้นอย่างอิสระรหัสในการสร้างคำสั่งอาจยาวและมีเงื่อนไขการแตกแขนงจำนวนมากซึ่งไม่สะดวกมากสำหรับการเพิ่มประสิทธิภาพและการดีบัก
3.sql
Hibernate ยังรองรับวิธีการสืบค้นที่ดำเนินการโดยตรง SQL วิธีนี้เสียสละข้อดีของการจำศีลข้ามฐานข้อมูลและเขียนคำสั่ง SQL พื้นฐานด้วยตนเองเพื่อให้ได้ประสิทธิภาพการดำเนินการที่ดีที่สุด
เมื่อเทียบกับสองวิธีแรกการเพิ่มประสิทธิภาพและการดีบักนั้นสะดวกกว่า
มาดูชุดตัวอย่างง่ายๆ
แพ็คเกจ com.cdai.orm.hibernate.query; นำเข้า Java.util.Arrays; นำเข้า java.util.list; นำเข้า org.hibernate.criteria; นำเข้า org.hibernate.query; นำเข้า org.hibernate.session; นำเข้า org.hibernate.sessionfactory; นำเข้า org.hibernate.cfg.annotationConfiguration; นำเข้า org.hibernate.criterion.criterion; นำเข้า org.hibernate.criterion.example; นำเข้า org.hibernate.criterion.expression; นำเข้า com.cdai.orm.hibernate.annotation.account; คลาสสาธารณะ BasicQuery {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {sessionFactory sessionFactory = new AnnotationConfiguration () addfile ("hibernate/hibernate.cfg.xml") กำหนดค่า () addpackage ("com.cdai.orm.hibernate.annotation") AddannotatedClass (บัญชี. class) BuildSessionFactory (); เซสชัน = sessionfactory.opensession (); // 1.HQL QUERY QUERY = Session.Createquery ("จากบัญชีเป็นที่ A.ID =: ID"); query.setLong ("id", 1); รายการผลลัพธ์ = query.list (); สำหรับ (แถววัตถุ: ผลลัพธ์) {system.out.println (แถว); } // 2.QBC เกณฑ์เกณฑ์ = Session.createCriteria (account.class); Criteria.add (expression.eq ("id", ใหม่ยาว (2))); ผลลัพธ์ = Criteria.list (); สำหรับ (แถววัตถุ: ผลลัพธ์) {system.out.println (แถว); } // 3.QBE ตัวอย่างบัญชี = บัญชีใหม่ (); example.setBalance (100); result = session.createCriteria (account.class) เพิ่ม (example.create (ตัวอย่าง)) รายการ(); สำหรับ (แถววัตถุ: ผลลัพธ์) {system.out.println (แถว); } // 4.SQL query = session.createsqlQuery ("เลือกอันดับ 10 * จากคำสั่ง tb_account โดย col_id desc"); ผลลัพธ์ = query.list (); สำหรับ (แถววัตถุ: ผลลัพธ์) {system.out.println (array.toString ((วัตถุ []) แถว)); } session.close (); -Hibernate: เลือก Account0_.col_id เป็น col1_0_, account0_.col_balance เป็น col2_0_ จาก tb_account accountion0_ โดยที่บัญชี 0_.col_id =? บัญชี [id = 1, ยอดคงเหลือ = 100] Hibernate: เลือกสิ่งนี้ this_.col_id =? บัญชี [id = 2, balance = 100] hibernate: เลือก this_.col_id เป็น col1_0_0_, this_.col_balance เป็น col2_0_0_ จาก tb_account this (this_.col_balance =?) desc [2, 100] [1, 100]
จากบันทึกคุณสามารถเห็นการควบคุมของ Hibernate อย่างชัดเจนเกี่ยวกับคำสั่ง SQL ที่สร้างขึ้น วิธีการสืบค้นที่เฉพาะเจาะจงในการเลือกขึ้นอยู่กับแอปพลิเคชันเฉพาะ