Hibernate(四):Hibernate的初始化,增刪改查等方法
1,Hibernate初始化類
package com.hibernate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateInit { private static SessionFactory sessionFactory=null; //SessionFactory和Configuration對整個應用來說,只有一個例項存在 //為使用者訪問定義了一個本地執行緒變數,是靜態的,對每一個訪問該執行緒的使用者產生一個例項 private static final ThreadLocal<Session> threadlocal=new ThreadLocal<Session>(); static { try{ Configuration cfg=new Configuration().configure(); sessionFactory=cfg.buildSessionFactory(); }catch (Exception e) { System.out.println("建立會話工廠失敗"); e.printStackTrace(); } } //要取得Session物件時,首先從當前使用者的執行緒取得Session物件。 //如果還沒有建立,從SessionFactory中建立一個Session //此時會判斷SessionFactory物件是否已經建立 //過程: //首先判斷threadLocal中是否存在Session物件 // 如果不存在 則建立Session物件 // 在建立Session物件時 首先要判斷系統是否已經載入Configuration // 如果沒有sessionFactory 則需要先建立該物件 // 建立完成的Session物件 需要儲存在threadLocal中以供本次訪問執行緒的下一次呼叫 public static Session getSession() throws HibernateException{ Session session=(Session)threadlocal.get(); if(session==null || !session.isOpen()) { if(sessionFactory==null) { rebulidSessionFactory(); } session=(sessionFactory!=null)?sessionFactory.openSession():null; threadlocal.set(session); } return session; } private static void rebulidSessionFactory() { try{ Configuration cfg=new Configuration().configure(); sessionFactory=cfg.buildSessionFactory(); }catch (Exception e) { System.err.println("建立會話工廠失敗"); e.printStackTrace(); } } public static SessionFactory getSessionFactory() { return sessionFactory; } // 在關閉Session物件是 只需要從當前執行緒中取得Session物件 關閉該物件 並置空本地執行緒變數即可 public static void closeSession() throws HibernateException{ Session session=(Session)threadlocal.get(); threadlocal.set(null); if(session!=null) { session.close(); } } }
2.儲存資料:
1. Session的save()方法是一個臨時物件轉變成持久化物件
2.完成以下操作:
- 將new物件加入到Session快取器中,使它進入持久化狀態
- 選用對映檔案指定識別符號生成器,為持久化物件分配唯一的OID,在使用代理主鍵的情況下,setId()方法為New物件設定的OID使用無效
- 計劃執行一條insert語句:在flush快取的時候
3. Hibernate 通過持久化物件的 OID 來維持它和資料庫相關記錄的對應關係. 當 News 物件處於持久化狀態時, 不允許程式隨意修改它的 ID
程式碼如下:
package com.Test; import com.Product.Product; import com.hibernate.HibernateInitialize; import org.hibernate.Session; public class AddProduct { /** * 新增商品 */ public static void main(String[] args) { Session session = null; //宣告Session物件 Product product = new Product();//例項化持久化類 //為持久化類屬性賦值 product.setName("Java Web程式設計寶典");//設定產品名稱 product.setPrice(79.00);//設定產品價格 product.setFactory("明日科技");//設定生產商 product.setRemark("無");//無 //Hibernate的持久化操作 try { session = HibernateInitialize.getSession();//獲取Session session.beginTransaction();//開啟事務 session.save(product);//執行資料庫新增操作 session.getTransaction().commit();//事務提交 } catch (Exception e) { session.getTransaction().rollback();//事務回滾 System.out.println("資料新增失敗"); e.printStackTrace(); }finally{ HibernateInitialize.closeSession();//關閉Session物件 } } }
執行完成後:
注意:持久化狀態product在建立後是瞬時狀態,在Session執行完save()後,持久化物件product狀態變為持久化狀態,但這時的資料庫操作並沒有交給資料庫,在事務執行commit()方法後,才完成資料庫的新增操作。此時的持久化物件product變為髒資料,Session關閉後,持久化物件product的狀態變為遊離狀態,最後被JVM回收
3.查詢資料:
Session物件提供了兩種物件裝載的方法:get()和load
(1)get()方法
- 如果不缺定資料庫中是否有匹配的記錄存在,就可以使用get()方法進行物件裝載、
- 它會立即訪問資料庫,如果資料庫中沒有匹配記錄在,會返回null(返回值可能是持久化物件,也可以是null)
- get()方法裡面有兩個引數:一個持久化物件,另一個是持久化物件中的唯一標識
程式碼如下:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class GetProduct {
public static void main(String[] args)
{
Session session=null;
try{
session= HibernateInitialize.getSession();
Product product=(Product)session.get(Product.class,new Integer(0));
System.out.println("產品名稱:"+product.getName());
System.out.println("產品價格:"+product.getPrice()+"元");
System.out.println("生產廠商:"+product.getFactory());
System.out.println("產品備註:"+product.getRemark());
}catch (Exception e)
{
System.out.println("物件裝載失敗");
}finally {
HibernateInitialize.closeSession();
}
}
}
在控制檯輸出資料,截圖如下:
(2)load()方法
返回物件的代理,只有在返回物件被呼叫時,Hibernate才會發出SQL語句去查詢物件
程式碼如下:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class LoadProduct {
public static void main(String[] args) {
Session session = null;
try {
//Hibernate的持久化操作
session = HibernateInitialize.getSession();//獲取Session
Product product = new Product();//例項化物件
session.load(product, new Integer("0"));//裝載物件
//Product product = (Product) session.load(Product.class, new Integer("1"));//裝載物件
System.out.println("產品ID:" + product.getId());
System.out.println("產品名稱:" + product.getName());
System.out.println("產品價格:" + product.getPrice() + "元");
System.out.println("生產廠商:" + product.getFactory());
System.out.println("產品備註:" + product.getRemark());
} catch (Exception e) {
System.out.println("物件裝載失敗");
e.printStackTrace();
} finally {
HibernateInitialize.closeSession();//關閉Session
}
}
}
在控制檯輸出資料,截圖如下:
(3)區別:
相同:都可以根據給定的OID從資料庫中載入一個持久化類物件
不同點:
- get方法會在呼叫之後立即向資料庫發出sql語句(不考慮快取的情況下),返回持久化物件;而load方法會在呼叫後返回一個代理物件,該代理物件只儲存了實體物件的id,直到使用物件的非主鍵屬性時才會發出sql語句。
- load()方法返回的是實體的代理類例項,,而get()方法永遠返回的是實體類
- 當資料庫中不存在與 OID 對應的記錄時, load() 方法丟擲 ObjectNotFoundException 異常, 而 get() 方法返回 null
4.刪除資料
(1)Session的delete()方法既可以刪除一個遊離物件,也可以刪除一個持久化物件
(2)處理過程:
- 計劃執行一條delete語句
- 把物件從Session快取中刪除,該物件進入刪除狀態
(3)Hibernate 的 cfg.xml 配置檔案中有一個 hibernate.use_identifier_rollback 屬性, 其預設值為 false, 若把它設為 true, 將改變 delete() 方法的執行行為: delete() 方法會把持久化物件或遊離物件的 OID 設定為 null, 使它們變為臨時物件
程式碼如下:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class deleteProduct {
public static void main(String[] args)
{Session session = null; //宣告Session物件
try {
//Hibernate的持久化操作
session = HibernateInitialize.getSession();//獲取Session
session.beginTransaction();
Product product = (Product) session.get(Product.class, new Integer("0"));//裝載物件
session.delete(product);//刪除持久化資訊
session.getTransaction().commit();
} catch (Exception e) {
System.out.println("物件刪除失敗");
e.printStackTrace();
} finally{
HibernateInitialize.closeSession();//關閉Session
}
}
}
截圖如下:
資料庫表截圖:
注意:在剛增加,查詢時都沒有開啟事務,提交事務,不會報錯。但在delete()方法中,是對持久化物件進行刪除,當持久化物件發生改動時並不會立即執行資料庫操作,只有當事務結束時,才會更新資料庫。所以必須使用事務
5.更新資料
(1)從資料庫中獲得物件,然後修改屬性,採用Session的flush()方法--是指Session執行一些必需的SQL語句來把記憶體中的物件狀態同步於JDBC中。刷出會在某些查詢之前執行,在事務提交時執行
//Hibernate的持久化操作
session = HibernateInitialize.getSession();//獲取Session
Product product = (Product) session.load(Product.class, new Integer("1"));//裝載物件
product.setName("Java Web程式設計詞典");//修改商品名稱
product.setRemark("無");//修改備註資訊
session.update(product );
session.flush();
(2)update()方法
update()方法是一個使一個遊離狀態轉變為持久化物件並且計劃執行一條update語句
- 若希望 Session 僅當修改了 News 物件的屬性時, 才執行 update() 語句, 可以把對映檔案中 <class> 元素的 select-before-update 設為 true. 該屬性的預設值為 false
- 當只更新物件一個屬性時,其他屬性也會被改變,可以把對映檔案中 <class> 元素的 dynamic-update設為true
- 當 update() 方法關聯一個遊離物件時, 如果在 Session 的快取中已經存在相同 OID 的持久化物件, 會丟擲異常
- 當 update() 方法關聯一個遊離物件時, 如果在資料庫中不存在相應的記錄, 也會丟擲異常.
程式碼:
package com.Test;
import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class UpdateProduct {
public static void main(String[] args)
{
Session session=null;
try
{
session= HibernateInitialize.getSession();
session.beginTransaction();
Product product=(Product)session.get(Product.class,new Integer(0));
product.setName("Java經典");
session.update(product);
session.getTransaction().commit();
}catch (Exception e)
{
e.printStackTrace();
}finally {
HibernateInitialize.closeSession();
}
}
}
控制檯輸出截圖:
資料庫截圖:
6.saveOrUpdate()方法
Session 的 saveOrUpdate() 方法同時包含了 save() 與 update() 方法的功能
判定物件為臨時物件的標準:
Java物件的OID為null
對映檔案中為 <id> 設定了 unsaved-value 屬性, 並且 Java 物件的 OID 取值與這個 unsaved-value 屬性值匹配
7.merge()方法
新new一個物件,如果該物件設定了ID,則這個物件就當作遊離態處理:
當ID在資料庫中不能找到時,用update的話肯定會報異常,然而用merge的話,就會insert。
當ID在資料庫中能找到的時候,update與merge的執行效果都是更新資料,發出update語句;
如果沒有設定ID的話,則這個物件就當作瞬態處理:
用update的話,由於沒有ID,所以會報異常,merge此時則會儲存資料,根據ID生產策略生成一條資料;