DAO bilan tanishuv
Ma'lumotlar bazasi bilan JDBC yoki hatto Hibernate orqali ishlaganda kod ko'pincha biz xohlagandan ham kattaroq bo'lib chiqadi. Ma'lumotlar bazasiga so'rovlar ko'pincha quyidagilarni o'z ichiga oladi:
- ma'lumotlarni tekshirish
- so'rov parametrlarini o'rnatish
- so'rov parametrlariga qarab HQL-so'rovni tanlash
- Criteria API yordamida so'rov tuzish
- keshlashni sozlash
- xatoliklarni dastlabki qayta ishlash va hokazo.
Shuning uchun umumiy amaliyot - ma'lumotlar bazasi bilan ishlash uchun maxsus sinflar yaratishdir. Bunday sinflar DAO, ya'ni Data Access Object, deb nomlanadi. Ularning vazifasi - ma'lumotlar bazasi bilan ishlashdagi barcha murakkabliklarni yashirish va tashqi tomonga chiroyli va qulay interfeys taqdim etish.
Misol:
public class EmployeeDAO {
public List<Employee> getEmployeeList(int from, int count) {
String hqlQuery = “from Employee”;
Query<Employee> query = session.createQuery(hqlQuery, Employee.class);
query.setFirstResult(from);
query.setMaxResults(count);
return query.getResultList();
}
public int getEmployeeCount() {
String hqlQuery = “select count(*) from Employee”;
Query<Integer> query = session.createQuery(hqlQuery, Integer.class);
return query.getSingleResult();
}
public Employee getEmployeeByUniqName(String name) {
String hqlQuery = “from Employee where name = :name”;
Query<Integer> query = session.createQuery(hqlQuery, Employee.class);
query.setParametуr(“name”, name);
return query.getSingleResult();
}
}
Bizda EmployeeDAO nomli sinf bor, u orqali biz ma'lumotlar bazasidan Employee turidagi obyektlarni olamiz. Sinf, ko'p annotatsiyalarga ega bo'lishiga qaramay, o'zini ma'lumotlar bazasida saqlash uchun metodlar o'z ichiga olmaydi.
DAO afzalliklari
Bunday yondashuvning afzalliklari juda ko'p:
Birinchidan, biz DAO sinfida ma'lumotlar bazasi bilan ishlashni to'liq yashirdik. Agar kelajakda barcha so'rovlarni HQL dan Criteria API yoki Native Query ga o'tkazishni istasangiz, bu sinf chegaralaridan tashqaridagi kodni hech qanday tarzda ta'sir qilmaydi.
Ikkinchidan, bu metodlarning xatti-harakatlarini murakkablashtirish mumkin. Keshlash, events, parametrlarni tekshirishni qo'shishingiz mumkin. Bu barchasi tashqi koddan yashiriladi.
Uchinchidan, agar sizga hozircha mavjud bo'lmagan metod kerak bo'lsa, oddiygina uni bu yerga qo'shasiz. Masalan, menga foydalanuvchi barcha muddati tugagan vazifalarni qaytaradigan metod kerak bo'lsa. Unda men shunday qilaman:
public class EmployeeDAO {
public List<Task> getExpiredTasks(int userId, int from, int count) {
String hqlQuery = “from Task where task.user.id = :id and deadline < curdate()”;
Query<Task> query = session.createQuery(hqlQuery, Task.class);
query.setFirstResult(from);
query.setMaxResults(count);
return query.getResultList();
}
public int getExpiredTasksCount(int userId) {
String hqlQuery = “select count(*) from Task where task.user.id = :id and deadline < curdate()”;
Query<Integer> query = session.createQuery(hqlQuery, Integer.class);
return query.getSingleResult();
}
}
Men sinfga ikki metod qo'shdim:
- getExpiredTasksCount() — foydalanuvchi uchun muddati tugagan vazifalar sonini qaytaradi
- getExpiredTasks() — foydalanuvchi uchun muddati tugagan vazifalar ro'yxatini qaytaradi
Menga metodlar kerak edi - men ularni qo'shdim. Va darhol foydalanishim mumkin. Keyin ularni optimallashtiraman.
Bundan tashqari, bu metodlarni Unit-testlar bilan qoplash mumkin, qayta yozish va optimallashtirishdan oldin, shunday qilib, biz ma'lumotlar bazasi bilan ishlash avvalgiday qolganini bilamiz.
Standart yondashuv
Ko'pincha DAO sinflarida bir xil metodlar mavjud bo'ladi. Masalan, quyidagilar:
| T getById(final long id) | Obyektni uning id ga qarab olish |
| List<T> getItems(int from, int count) | Berilgan diapazon bo'yicha obyektlar ro'yxatini olish |
| List<T> getAll() | Ushbu turdagi barcha obyektlarni olish |
| int getCount() | Obyektlar sonini bilish |
| T save(final T entity) | Obyektni bazaga saqlash |
| T update(final T entity) | Obyektni bazada yangilash |
| void delete(final T entity) | Obyektsni bazadan o'chirish |
| void deleteById(final long entityId) | Obyektsni id ga qarab bazadan o'chirish |
Bu metodlar deyarli har bir DAO sinfda uchraydi. Agar biror DAO sinf bo'lsa, 90% ehtimol bilan unda bunday metodlar bo'ladi.
Ha, boshqa metodlar ham bo'lishi mumkin, lekin bunday metodlar ham bo'ladi. Chunki bu juda qulay. Bu ma'lumotlar bazasi yoki Hibernate bilan bevosita ishlashni oldini olishga yordam beradi.
Agar bir xil metodlar mavjud bo'lsa, ularni nima qilish kerak? To'g'ri, ularni asosiy sinfga chiqarish kerak.
U taxminan shunday ko'rinadi:
public abstract class AbstractHibernateDao<T > {
private final Class<T> clazz;
private SessionFactory sessionFactory;
public AbstractHibernateDao(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
public T getById(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
public List<T> getItems(int from, int count) {
Query query = getCurrentSession().createQuery(clazz , "from " + clazz.getName())
query.setFirstResult(offset);
query.setMaxResults(count);
return query.singleResult();
}
public List<T> findAll() {
return getCurrentSession().createQuery(clazz, "from " + clazz.getName()).list();
}
public T create(final T entity) {
getCurrentSession().saveOrUpdate(entity);
return entity;
}
public T update(final T entity) {
return (T) getCurrentSession().merge(entity);
}
public void delete(final T entity) {
getCurrentSession().delete(entity);
}
public void deleteById(final long entityId) {
final T entity = getById(entityId);
delete(entity);
}
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
Va shunda bizning EmployeeDAO quyidagicha ko'rinadi:
public class EmployeeDAO extends AbstractHibernateDAO<Employee> {
public EmployeeDAO (){
super(Employee.class );
}
}
Va TaskDAO esa shunday:
public class TaskDAO extends AbstractHibernateDAO<Task> {
public TaskDAO (){
super(Task.class );
}
}
Ikki sinfda ham biz AbstractHibernateDAO da e'lon qilgan barcha metodlar mavjud bo'ladi. Unifikatsiya - bu juda qulay va amaliy.
GO TO FULL VERSION