วิธีการsynchronized
ทำงานของคีย์เวิร์ด Java
เมื่อคุณเพิ่มsynchronized
คำหลักไปยังวิธีการแบบคงที่วิธีการสามารถเรียกได้โดยเธรดเดียวเท่านั้นในแต่ละครั้ง
ในกรณีของคุณทุกวิธีการโทรจะ:
- สร้างใหม่
SessionFactory
- สร้างใหม่
Session
- ดึงเอนทิตี
- คืนเอนทิตีกลับไปที่ผู้โทร
อย่างไรก็ตามสิ่งเหล่านี้เป็นข้อกำหนดของคุณ:
- ฉันต้องการสิ่งนี้เพื่อป้องกันการเข้าถึงข้อมูลไปยังอินสแตนซ์ฐานข้อมูลเดียวกัน
- ป้องกัน
getObjectById
การถูกเรียกสำหรับคลาสทั้งหมดเมื่อมีการเรียกโดยคลาสเฉพาะ
ดังนั้นแม้ว่าgetObjectById
เมธอดจะปลอดภัยต่อเธรดการใช้งานนั้นไม่ถูกต้อง
SessionFactory
ปฏิบัติที่ดีที่สุด
SessionFactory
เป็นด้ายปลอดภัยและเป็นวัตถุที่มีราคาแพงมากในการสร้างตามความต้องการที่จะแยกชั้นเรียนกิจการและสร้างตัวแทน metamodel นิติบุคคลภายใน
ดังนั้นคุณไม่ควรสร้างการเรียกใช้เมธอดSessionFactory
ทุกครั้งgetObjectById
คุณควรสร้างอินสแตนซ์ซิงเกิลแทน
private static final SessionFactory sessionFactory = new Configuration()
.configure()
.buildSessionFactory();
Session
ควรถูกปิด
คุณไม่ได้ปิดSession
ในfinally
บล็อกและสิ่งนี้สามารถรั่วไหลของทรัพยากรฐานข้อมูลหากมีข้อผิดพลาดเกิดขึ้นเมื่อโหลดเอนทิตี
ตามSession.load
วิธีการ JavaDocอาจโยน a HibernateException
หากไม่พบเอนทิตีในฐานข้อมูล
คุณไม่ควรใช้วิธีนี้เพื่อตรวจสอบว่ามีอินสแตนซ์อยู่หรือไม่ (ใช้get()
แทน) ใช้สิ่งนี้เพื่อดึงอินสแตนซ์ที่คุณถือว่ามีอยู่เท่านั้นโดยที่การไม่มีอยู่จริงจะเป็นข้อผิดพลาดจริง
นั่นเป็นเหตุผลที่คุณต้องใช้finally
บล็อกเพื่อปิดSession
เช่นนี้:
public static synchronized Object getObjectById (Class objclass, Long id) {
Session session = null;
try {
session = sessionFactory.openSession();
return session.load(objclass, id);
} finally {
if(session != null) {
session.close();
}
}
}
การป้องกันการเข้าถึงแบบหลายเธรด
ในกรณีของคุณคุณต้องการให้แน่ใจว่ามีเพียงหนึ่งเธรดเท่านั้นที่สามารถเข้าถึงเอนทิตีนั้น
แต่synchronized
คำหลักป้องกันไม่ให้สองเธรดเรียกgetObjectById
พร้อมกันเท่านั้น หากทั้งสองเธรดเรียกใช้เมธอดนี้หลังจากที่อื่นคุณจะยังคงมีสองเธรดที่ใช้เอนทิตีนี้
ดังนั้นถ้าคุณต้องการล็อควัตถุฐานข้อมูลที่กำหนดดังนั้นไม่มีเธรดอื่นสามารถแก้ไขได้ดังนั้นคุณต้องใช้การล็อคฐานข้อมูล
synchronized
คำหลักที่ทำงานเฉพาะใน JVM เดียว หากคุณมีหลายเว็บโหนดจะไม่ป้องกันการเข้าถึงหลายเธรดใน JVM หลายรายการ
สิ่งที่คุณต้องทำคือใช้LockModeType.PESSIMISTIC_READ
หรือLockModeType.PESSIMISTIC_WRITE
ขณะใช้การเปลี่ยนแปลงกับฐานข้อมูลเช่นนี้:
Session session = null;
EntityTransaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.getTransaction();
tx.begin();
Post post = session.find(
Post.class,
id,
LockModeType.LockModeType.PESSIMISTIC_READ
);
post.setTitle("High-Performance Java Perisstence");
tx.commit();
} catch(Exception e) {
LOGGER.error("Post entity could not be changed", e);
if(tx != null) {
tx.rollback();
}
} finally {
if(session != null) {
session.close();
}
}
ดังนั้นนี่คือสิ่งที่ฉันทำ:
- ฉันสร้างใหม่
EntityTransaction
และเริ่มทำธุรกรรมฐานข้อมูลใหม่
- ฉันโหลด
Post
เอนทิตีในขณะที่ล็อคล็อกในฐานข้อมูลที่เกี่ยวข้อง
- ฉันเปลี่ยน
Post
เอนทิตีและยอมรับธุรกรรม
- ในกรณีที่มี
Exception
การโยนฉันย้อนกลับการทำธุรกรรม
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ ACID และฐานข้อมูลธุรกรรมตรวจสอบบทความนี้เช่นกัน