4.1 Tranzaksiyalar va ma'lumotlar bazasi yaxlitligi
Ma'lumotlar bazasi bilan odatiy ish rejimi — har daqiqada unga yuzlab turli mijozlardan minglab so'rovlar kelib tushadi. Bu paytda ko'pincha bir xil ma'lumotlarga turli so'rovlar kelishi vaziyatlari yuzaga keladi.
Kamdanki, lekin vaqti-vaqti bilan, bir so'rov biror satrni o'qiyotganda, boshqa so'rov esa uni o'zgartirayotgani holatlar yuzaga keladi. Tasavvur qiling, agar kimdir faqat yarim o'zgartirilgan satrni o'qisa nima bo'ladi? Yaxshi narsa emas.
Bu muammo bir nechta usul bilan hal qilinadi. Birinchisi, o'zgartirilayotgan satrni lock qilish. Ham o'qish, ham yozish uchun. Bu usul ishlaydi, lekin baza tezligi sezilarli darajada pasayadi.
Ikkinchi usul — satrni faqat yozish uchun lock qilish. Bu holatda ham kimdir qisman o'zgartirilgan satrni o'qimoqchi bo'lganida muammo bo'ladi. Xulosa — satr qisman o'zgartirilgan holat bo'lmasligi kerak.
Shuning uchun uchinchi usul — tranzaksiyalar ixtiro qilindi. Tranzaksiya — bu guruh harakatlari, ular hammasi birga yoki hech biri amalga oshiriladi. Harakatlar qismining bajarilib, ikkinchi qismi bajarilmagan holat bo'lolmaydi. Agar barcha o'zgarishlarni kiritish mumkin bo'lmasa, kiritilgan barcha o'zgarishlar orqaga qaytariladi.
Har qanday zamonaviy SQL-server ma'lumotlarni faqat tranzaksiyalarda o'zgartirish imkonini beradi. Siz tranzaksiyani ochasiz, istalgan sonli jadvalga istalgan o'zgarishlarni kiritasiz, va tranzaksiyani commit qilasiz. Keyin SQL-server o'zgartirishlarni kiritishga harakat qiladi. Agar hamma narsa yaxshi bo'lsa, ular umumiy ma'lumotlar bazasiga qo'shiladi. Agar muammolar bo'lsa, barcha o'zgarishlar bekor qilinadi.
Hibernate ham bu paradigmadan foydalanadi. Shuning uchun oldingi leksiyada Employee ob'ektini ma'lumotlar bazasiga saqlashga urinishda avval tranzaksiya ochilishi, va saqlashdan keyin commit qilinishi ko'rilgan edi.
Biz bu mavzuni batafsilroq ko'rib chiqamiz, hozircha esa tranzaksiyalar nima uchun kerak va ular qayerda qo'llanilishini bilsangiz kifoya.
4.2 Ob'ektlarni olish
Agar Hibernate ma'lumotlarni olish uchun so'rov bajarayotgan bo'lsa, tranzaksiyani ochishni aniq qilish shart emas. Agar kerak deb hisoblasa, Hibernate o'zi buni qiladi: unda o'zining sozlamalari, shuningdek SQL-serverning sozlamalari mavjud.
Biz esa siz bilan ma'lumotlar bazasi bilan ishlash usullarini ko'rib chiqamiz. Va eng oddiy usullardan biri — bu ob'ektni uning ID bo'yicha olish. Buning uchun session ob'ekti get() metodidan foydalanish kerak. Bunday so'rovning umumiy ko'rinishi:
Klass ism = session.get(Klass.class, ID);
Misol:
public User getUserById(Integer id) {
try (Session session = sessionFactory.openSession()) {
User user = session.get(User.class, id);
return user;
}
}
4.3 Ob'ektlarni saqlash (qo'shish)
Agar siz ob'ektingizni ma'lumotlar bazasiga saqlamoqchi bo'lsangiz, SQL darajasida INSERT so'rovi bajariladi. Shuning uchun amallaringizni alohida tranzaksiya ko'rinishida bajarishingiz kerak. Bundan tashqari, saqlash uchun yaxshiroq session ob'ekti persist() metodidan foydalanish yaxshi.
Bunday so'rovning umumiy ko'rinishi:
session.persist(Ob'ekt);
persist() metodi nafaqat bazani, balki o'zini ham o'zgartiradi. Gap shundaki, ob'ektni ma'lumotlar bazasiga qo'shsak, bu ob'ektning hali ID mavjud emas. Odatda shunday, garchi istisnolar bo'lsa ham. Va qo'shgandan so'ng, ob'ektning ID mavjud bo'ladi.
public boolean saveUser(User user) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.persist(user);
transaction.commit();
return true;
}
catch() {
return false;
}
}
Shuningdek, Session ob'ekti save() metodiga ega bo'lib, u o'xshash funktsiyani bajaradi. Faqat save() metodi — bu eski Hibernate standardi, va persist() metodi — bu JPA standardi.
4.4 Ob'ektlarni o'chirish
Agar mavjud ob'ektni o'chirmoqchi bo'lsangiz, buni qilish juda oson. Buning uchun session ob'ekti maxsus remove() metodiga ega.
Bunday so'rovning umumiy ko'rinishi:
session.remove(Ob'ekt);
Albatta, misol bilan kodni yozamiz:
public boolean removeUser(User user) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.remove(user);
transaction.commit();
return true;
}
catch() {
return false;
}
}
Nima uchun shuncha murakkab, deb so'raysanmi?
Yaxshi, birinchidan, har qanday ma'lumotlar bazasidagi o'zgarishlar har doim turli va har doim aniq bo'lmagan oqibatlarga olib keladi. Ikkinchidan, ushbu ob'ekt bilan bog'liq bo'lishi mumkin bo'lgan tug'ilgan ob'ektlar va h.k. bo'lgan. Shunday qilib, o'chirish ssenariylari ko'pincha murakkab bo'ladi.
GO TO FULL VERSION