持久化:將內存中的對象持久化到數據庫中的過程就是持久化。Hibernate 就是用來進行持久化的框架。html
持久化類:一個 Java 對象與數據庫的表創建了映射關係,那麼這個類在 Hibernate 中稱爲是持久化類。java
一、對持久化類提供一個無參構造方法。sql
二、屬性須要私有,對私有屬性提供 public 的 get 和 set 方法。數據庫
三、對持久化類提供一個惟一標識 OID 與數據庫表主鍵對應。數組
Java 中經過對象的地址區分是不是同一個對象,數據庫中經過主鍵區分是不是同一條記錄,而在 Hibernate 中是經過持久化類的 OID 屬性區分是不是同一個對象。緩存
四、持久化類中屬性儘可能使用包裝類類型。session
五、持久化類不要用 final 修飾。框架
Hibernate 是持久層的框架,經過持久化類完成 ORM 操做。爲了更好的管理,Hibernate 將持久化類對象分爲了三種狀態。ide
沒有惟一標識 OID,且沒有被 session 管理。工具
有惟一標示 OID,且沒有被 session 管理。
有惟一標識 OID,且被 session 管理。
Session session1 = HibernateUtil.openSession(); Transaction transaction1 = session1.beginTransaction(); Customer customer = new Customer(); // 瞬時態:無惟一標識,未被 session1 管理。 customer.setCust_id(1L); // 未被 session1 管理,若是數據庫數據有與之對應的惟一標示(即數據庫表中有一行 cust_id=1 的數據),則爲遊離態,不然依舊是瞬時態。 customer.setCust_name("李四"); session1.saveOrUpdate(customer); // 交由 session1 管理,且數據庫數據有對應惟一標示的數據,轉爲持久態。 transaction1.commit(); session1.close(); Session session2 = HibernateUtil.openSession(); Transaction transaction2 = session2.beginTransaction(); System.out.println(customer); // 以前託管到的 session1 已關閉,即未被 session1 也未被 session2 管理,但有與數據庫數據對應的惟一標識,此時爲遊離態。 session2.delete(customer); // session2 主動放棄管理,且從數據庫中刪除與惟一標示對應的記錄,轉爲瞬時態。 transaction2.commit(); session2.close(); /* 總結: 瞬時態對象 得到: Customer customer = new Customer(); 狀態轉換: ->持久態: session.save(customer); 、 session.saveOrUpdate(customer); ->遊離態: customer.setCust_id(1L); 遊離態對象 得到: Customer customer = new Customer();customer.setCust_id(1L); 狀態轉換: ->持久態 session.update(customer); 、 session.saveOrUpdate(customer); ->瞬時態: customer.setCust_id(null); 持久態對象 得到: session.get(Customer.class,1L); 、 session.load(Customer.class,1L); 狀態轉換: ->瞬時態: session.delete(customer); ->遊離態: session.close(); 、 session.clear(); 、 session1.evict(customer); */
主鍵自己就是表中有意義的字段。
主鍵自己不是表中必須的字段。
一旦天然主鍵參與到業務邏輯中,後期就有可能修改源代碼。
好的程序設計知足 OCP 原則,對程序的擴展是 open 的,對修改源碼是 close 的。
hibernate 提供的自動增加機制,使用 short 、int 、long 類型的主鍵,在單線程程序中使用。
適用 short 、int 、long 類型的主鍵,使用的是數據庫底層的自增機制,適用於有自增機制的數據庫(MySQL、MSSQL)。
適用 short 、int 、long 類型的主鍵,採用的是序列的方式,適用於支持序列機制的數據庫(Oracle)。
適用於字符串類型主鍵,由 Hibernate 隨機生成字符串主鍵。
本地策略,能夠在 identity 和 sequence 間自動切換。
Hibernate 放棄主鍵的管理,經過手動編碼給主鍵賦值。
依賴外部主鍵,適用於一對一關聯映射狀況下使用。
一種優化的方式,將數據放入內存中,使用的時候直接從內存中取,不用經過存儲源。
Hibernate 提供了兩種緩存機制:一級緩存、二級緩存。
是 Session 級別的緩存,一級緩存生命週期與 Session 一致,由 Session 中一系列 Java 集合構成,自帶不可卸載。
Hibernate 的一級緩存就是指 Session 緩存,Session 緩存是一塊內存空間,用來存放管理的持久化類對象,在使用 Hibernate 查詢對象時,首先會使用對象屬性的惟一標示 OID 值在一級緩存中進行查找,若是找到匹配的 OID 值的對象,就直接將該對象從一級緩存中取出使用,不會再查詢數據庫;若是沒有找到相同 OID 值的對象,則會去數據庫中查找相應數據。當從數據庫中查詢到所需數據時,該數據信息也會放置到一級緩存中。
在 Session 接口的實現中包含一系列 Java 集合,這些 Java 集合構成了 Session 緩存。只要 Session 實例未結束生命週期,存放在它緩存中的持久化類對象也不會結束生命週期。因此一級緩存也被稱爲 Session 級別的緩存。
Session session = HibernateUtil.openSession(); Customer customer1 = session.get(Customer.class, 1L);// 發出 select 的 SQL 語句 Customer customer2 = session.get(Customer.class, 1L);// 無 SQL 發出,只是取出上一行查詢出的放到一級緩存的 customer1 賦值給 customer2 System.out.println(customer1 == customer2);// true :即 customer1 和 customer2 是同一個對象 session.close();
Session session = HibernateUtil.openSession(); Transaction transaction = session.beginTransaction(); Customer customer1 = new Customer(); customer1.setCust_name("郭德綱"); Serializable id = session.save(customer1); // 在事務提交時發出 insert 的 SQL 語句,且將保存的對象放入一份到一級緩存中 Customer customer2 = session.get(Customer.class, id); // 無 SQL 語句發出,只是取上一行新增時保存到一級緩存中的 customer1 賦值給 customer2 System.out.println(customer1 == customer2);// true :即 customer1 和 customer2 是同一個對象 transaction.commit(); session.close();
Session session = HibernateUtil.openSession(); Transaction transaction = session.beginTransaction(); Customer customer1 = new Customer(); customer1.setCust_id(1L); customer1.setCust_name("郭德綱"); session.update(customer1); // 在事務提交時發出 update 的 SQL 語句,且將要更新的對象放入一份到一級緩存中 Customer customer2 = session.get(Customer.class, 1L); // 無 SQL 語句發出,只是取上一行更新時保存到一級緩存中的 customer1 賦值給 customer2 System.out.println(customer1 == customer2);// true :即 customer1 和 customer2 是同一個對象 transaction.commit(); session.close();
當 Hibernate 將持久化類對象放入一級緩存時,並不只僅只是放入一份,還拷貝了一份放入了一級緩存中的一個特殊區域-快照區。而 Hibernate 利用這個快照區實現了持久化類對象的一個特性,看以下示例:
Session session = HibernateUtil.openSession(); Customer customer = session.get(Customer.class, 1L); Transaction transaction = session.beginTransaction(); customer.setCust_name("郭德綱"); // session.update(customer); // 即使省略這個更新操做,在事務提交時 Hibernate 仍然會發出更新的 SQL 語句。 transaction.commit(); session.close();
當咱們使持久化類對象的屬性發生改變時,一級緩存中對應的持久化對象也會隨之發生改變,而快照區對應的持久化對象不變。而當事務提交時,Hibernate 會對比一級緩存中存放的持久化類對象和它對應快照中存放的持久化類對象。若是有差別,Hibernate 則幫咱們執行更新操做;若是沒有差別,則不會對數據庫進行操做。
在覈心配置文件 hibernate.cfg.xml 中添加以下屬性便可:
<!-- 配置事務隔離級別,有以下四個值: 1 :讀未提交 (Read uncommitted) 2 :讀已提交 (Read committed) 4 :可重複讀 (Repeatable read) 默認級別 8 :串行化 (Serializable) --> <property name="hibernate.connection.isolation">4</property>
在覈心配置文件 hibernate.cfg.xml 中添加以下屬性:
<!-- thread : Session 對象的生命週期與本地線程綁定。 jta : Session 對象的生命週期與 JTA 事務綁定。 managed : Hibernate 委託程序來管理 Session 對象的生命週期。 --> <property name="hibernate.current_session_context_class">thread</property>
而後就能夠保證在當前線程中經過 org.hibernate.SessionFactory.getCurrentSession 方法獲取到的 Session 是同一個實例。抽取工具類:
package com.zze.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { public static final Configuration cfg; public static final SessionFactory sf; static { cfg = new Configuration().configure(); sf = cfg.buildSessionFactory(); } public static Session openSession() { return sf.openSession(); } public static Session getCurrentSession() { return sf.getCurrentSession(); } }
HQL (Hibernate Query Language) ,相對 sql 來講,sql 中的表名在 hql 中用類名替代,sql 中的列名在 hql 中用屬性名替代。
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); String hql = "from Customer"; // 簡單查詢 Query query = currentSession.createQuery(hql); List<Customer> customerList = query.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); String hql = "from Customer where cust_name like ?"; Query query = currentSession.createQuery(hql); query.setParameter(0, "張%"); List<Customer> customerList = query.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); String hql = "from Customer"; Query query = currentSession.createQuery(hql); query.setFirstResult(2); // 起始索引,從 0 開始 query.setMaxResults(2); // 每頁條數 List<Customer> customerList = query.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
QBC (Query By Criteria) API 提供了檢索對象的另外一種方式,它主要由 Criteria 接口、Criterion 接口和 Expresson 類組成,它支持在運行時動態生成查詢語句,是一種更面向對象的查詢方式。
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); Criteria criteria = currentSession.createCriteria(Customer.class); List<Customer> customerList = criteria.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); Criteria criteria = currentSession.createCriteria(Customer.class); criteria.add(Restrictions.like("cust_name", "張", MatchMode.END)); List<Customer> customerList = criteria.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); Criteria criteria = currentSession.createCriteria(Customer.class); criteria.setFirstResult(2); criteria.setMaxResults(2); List<Customer> customerList = criteria.list(); for (Customer customer : customerList) { System.out.println(customer); } transaction.commit();
Hibernate 也支持咱們使用原生 SQL 查詢。
Session currentSession = HibernateUtil.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); SQLQuery sqlQuery = currentSession.createSQLQuery("select * from customer"); // 默認返回一個 Object 數組對象的列表,數組的每一項對應數據庫中每一行數據的一列 List<Object[]> customerList = sqlQuery.list(); for (Object[] customer : customerList) { System.out.println(String.format("id:%s,cust_name:%s", customer[0], customer[1])); } transaction.commit();
Session session = HibernateUtil.getCurrentSession(); session.beginTransaction(); String sql = "select * from customer where cust_name like ?"; SQLQuery sqlQuery = session.createSQLQuery(sql); sqlQuery.addEntity(Customer.class); sqlQuery.setParameter(0,"張%"); List<Customer> customerList = sqlQuery.list(); for (Customer customer : customerList) { System.out.println(customer); } session.getTransaction().commit();
Session session = HibernateUtil.getCurrentSession(); session.beginTransaction(); String sql = "select cust_id id,cust_name name from customer"; SQLQuery sqlQuery = session.createSQLQuery(sql); sqlQuery.addScalar("id", new LongType()); sqlQuery.addScalar("name"); sqlQuery.setResultTransformer(Transformers.aliasToBean(Customer2.class)); List<Customer2> userList = (List<Customer2>)sqlQuery.list(); for (Customer2 customer2 : userList) { System.out.println(customer2); } session.getTransaction().commit();