1. 程式人生 > >Hibernate 快取 之 Session 實現(一)

Hibernate 快取 之 Session 實現(一)

首先以查詢學生為例,模擬一個快取的機制

public class Test {
    public static void main(String[] args) throws Exception {
       MyClassDao myClassDao = new MyClassDao();
       StudentDao studentDao = new StudentDao();
      
       Student student1 = studentDao.findById("4028810027d8be080127d8be0d790002");
       System.out.println(student1.getName());
       Student student2 = studentDao.findById("4028810027d8be080127d8be0d790002");
       System.out.println(student2.getName());
    }
}
很明顯的看到執行了兩條SQL語句,感覺有點浪費資源,如果我們把第一次查詢的結果儲存起來,當第二次查詢的時候,先看儲存了沒有,如果有,直接用,如果沒有,則再查詢資料庫.這樣就更好一些.
修改StudentDao層,給Dao類增加一個模擬的快取集合

public class StudentDao {
    public static Map<String, Student> cache = new HashMap<String, Student>();
    
    public void create(Student student) throws Exception {
        Session session = null;
        Transaction transaction = null;
        try{
            session = HibernateUtil.getSession();
            transaction = session.getTransaction();
            transaction.begin();
            session.save(student);
            transaction.commit();
        }catch (Exception e){
            transaction.rollback();
            throw e;
        }
    }

    public void delete(Student student) throws Exception {
        Session session = null;
        Transaction transaction = null;
        try{
            session = HibernateUtil.getSession();
            transaction = session.getTransaction();
            transaction.begin();
            session.delete(student);
            transaction.commit();
           }catch (Exception e) {
            transaction.rollback();
            throw e;
        }
    }

    public Student findById(Serializable id) throws Exception {
       Session session = null;
       Transaction transaction = null;
       Student student = null;
       // 如果 快取中有 先使用快取的結果 返回輸出
       String key = Student.class.getName() + id;
       student = cache.get(key);
       if (student != null) {
        return student;
       }
       try {
        session = HibernateUtil.getSession();
        transaction = session.getTransaction();
        transaction.begin();
        student = (Student) session.get(Student.class, id);
        cache.put(key, student);
        transaction.commit();
       } catch (Exception e) {
        transaction.rollback();
        throw e;
       }
       return student;
    }
}
再一次執行Test 的 main方法。

只執行了一次查詢,這就是快取的一個作用,但是快取機制遠遠不會這麼簡單,想一下,如果在兩次查詢之間,物件更新了怎麼辦,這就涉及到快取的更新.我們暫時只需要瞭解一下快取的機制與簡單的實現.因為這一塊已經有現成的包和類直接用,不需要我們再從頭開發.

快取的作用主要是用來提高效能,可以簡單的理解成一個Map,使用快取涉及到三個操作:
把資料放入快取
從快取中獲取資料
刪除快取中無效資料

一級快取: Session 級共享,此快取只能在 Session 關閉之前使用.
save, update, saveOrUpdate, get, list, iterate, lock 這些方法都會將物件放在一級快取中, 一級快取不能控制快取的數量, 所以,要注意大批量操作資料時可能造成內在溢位。可以用evict, clear方法清除快取中的內容.後面 Hibernate 批量增加資料時再演示。
看下面的程式碼:

public Student findById(Serializable id) throws Exception {
   Session session = null;
   Transaction transaction = null;
   Student student = null;

   try {
    session = HibernateUtil.getSession();
    transaction = session.getTransaction();
    transaction.begin();
    student0 = (Student0) session.get(Student.class, id);
    System.out.println(student0.getName());
    Student student1 = (Student) session.get(Student.class, id);
    System.out.println(student1.getName());
    transaction.commit();
   } catch (Exception e) {
    transaction.rollback();
    throw e;
   }
   return student0;
}
可以看到上面的程式碼中,只查詢了一次資料庫,但是快取的作用域太小,沒有太大的作用.