hibernate的持久化類
- 持久化:將內存中的一個對象持久化到數據庫中的過程,hibernate就是一個用來進行持久化的框架
- 持久化類:一個Java對象與數據庫中表建立了關係映射,那麼這個類在hibernate中就可以稱之為持久化類
- Java實體類
- 該Java類的映射文件
持久化類的使用
提供無參構造
從之前測試類中查詢的使用來看:
User user = session.get(User.class, 1);
説明hibernate內部是使用反射技術實現生成對象實例,所以持久化類中的Java實體類必須提供一個無參構造
定義私有屬性,公有的getter/setter方法
hibernate生成對象實例時,需要獲取、設置屬性值
定義唯一標識屬性OID(對應數據庫表中的主鍵)
- hibernate緩存是一個map,他會根據OID作為緩存對象的key,我們的映射文件中<id>標籤指定的屬性值會作為OID
- Java對象通過地址來定位一個對象,數據庫的表中通過主鍵來定位到一條數據記錄
- hibernate中通過持久化類的唯一標識屬性來定位一個對象
例如User中的id
public class User {
private Integer id;
private String name;
private String password;
......
}
映射文件配置id屬性
<hibernate-mapping>
<!-- 配置表與實體的映射關係 -->
<class name="com.qf.entity.User" table="user">
<id name="id" column="id">
<generator class="native"></generator>
</id>
......
</class>
</hibernate-mapping>
屬性定義最好使用包裝類
因為基本數據類型默認值是0,容易出現很多問題
例如:
- 保存數據時,id屬性如果沒有設置具體值,默認使用0,保存兩次就會出現異常
- 表中某些字段值是0,無法區分是沒存值還是存的值就是0
最好不要使用final修飾持久化類
- 主要原因是影響延遲加載的使用,延遲加載是用於優化hibernate的
- 延遲加載返回的是一個代理對象,hibernate延遲加載是使用javassist技術來實現的
- javassist可以對沒有實現接口的類產生代理,使用字節碼增強技術繼承這個類並進行代理
- final修飾的類無法被繼承,那麼就無法產生代理對象,也就不能做延遲加載了(get方法和load方法的查詢完全一致)
主鍵
主鍵分類
- 自然主鍵:就是充當主鍵的字段本身具有一定的含義,是構成記錄的組成部分,比如學生的學號,除了充當主鍵之外,同時也是學生記錄的重要組成部分
- 代理主鍵:就是充當主鍵的字段本身不具有業務意義,只具有主鍵作用,比如自動增長的ID
- 實際開發中推薦使用代理主鍵,因為不涉及業務邏輯,後期不會發生修改源代碼的情況(OCP原則)
主鍵生成策略
<hibernate-mapping>
<!-- 配置表與實體的映射關係 -->
<class name="com.qf.entity.User" table="user">
<id name="id" column="id">
<!-- 主鍵生成策略 -->
<generator class="native"></generator>
</id>
<property name="name" column="name"/>
<property name="password" column="password"/>
</class>
</hibernate-mapping>
increment
- 由Hibernate從數據庫中取出主鍵的最大值(每個session只取1次),以該值為基礎,每次增量為1
- 適用於int、short、long類型的主鍵
- 線程不安全,適用於單線程程序
identity
- identity由底層數據庫生成標識符
- identity是由數據庫自己生成的,但這個主鍵必須設置為自增長,使用identity的前提條件是底層數據庫支持自動增長字段類型
- 適用DB2、SQL Server、MySQL、Sybase和HypersonicSQL,不適用Oracle
- 適用於int、short、long類型的主鍵
- 線程安全
sequence
- 採用數據庫提供的sequence機制生成主鍵,需要數據庫支持sequence
- oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence適用,Mysql不適用
- 適用於int、short、long類型的主鍵
uuid
- Hibernate在保存對象時,生成一個UUID字符串作為主鍵,保證了唯一性,但其並無任何業務邏輯意義,只能作為主鍵
- 唯一缺點長度較大,32位(Hibernate將UUID中間的“-”刪除了)的字符串,佔用存儲空間大
- Hibernate在維護主鍵時,不用去數據庫查詢,從而提高效率,而且它是跨數據庫的,以後切換數據庫極其方便
native(常用)
- native由hibernate根據使用的數據庫自行判斷採用identity、hilo、sequence其中一種作為主鍵生成方式,靈活性很強
assigned
- Hibernate不負責維護主鍵生成
- 人為控制主鍵生成,存儲對象前,必須要使用主鍵的setter方法給主鍵賦值
foreign
- 使用另外一個相關聯的對象的主鍵作為該對象主鍵
- 主要用於一對一關係中
持久化類的狀態
狀態
- 瞬時態:沒有唯一標識OID(映射到數據庫表的主鍵上具體的值),也不被session管理
- 持久態:有唯一標識OID,被session管理
- 脱管態:有唯一標識OID,不被session管理
@Test
public void save(){
Session session = SessionFactoryUtil.getSession();
Transaction ts = session.beginTransaction();
//瞬時態對象:新建對象,還沒有唯一標識OID,也沒有被session對象管理
User user = new User("hz", "0");
//持久態對象:有唯一標識OID,並且被session對象管理
Serializable save = session.save(user);
System.out.println("user:"+user);
ts.commit();
session.close();
//脱管態對象:session銷燬了,不被session對象管理,但是還有唯一標識OID
System.out.println("user:"+user);
}
幾種狀態的轉換
瞬時態對象
獲取:User user = new User();
轉換
- 轉換成持久態對象:save()、saveOrUpdate()
- 轉換成脱管態對象:user.setId(2);
持久態對象
獲取:get()、load()、find()、iterate()
轉換
- 轉換成瞬時態對象:delete()
- 轉換成脱管態對象:
- session.close():銷燬session對象
- session.clear():清空所有對象
- session.evict(obj):清空某一個對象
脱管態對象
獲取:User user = new User(3,"","");或者User user = new User(); user.setId(3);
轉換
- 轉換成瞬時態對象:user.setId(null);
- 轉換成持久態對象:update()、saveOrUpdate()、lock()
持久態對象可以自動更新數據庫
@Test
public void test(){
Session session = SessionFactoryUtil.getSession();
Transaction ts = session.beginTransaction();
//獲得持久化對象
User user = session.get(User.class, 1);
System.out.println("name:"+user.getName());
user.setName("test");
ts.commit();
session.close();
}
控制枱輸出
Hibernate:
select
user0_.id as id1_0_0_,
user0_.name as name2_0_0_,
user0_.password as password3_0_0_
from
user user0_
where
user0_.id=?
name:wxf
Hibernate:
update
user
set
name=?,
password=?
where
id=?
再次執行test()方法,console輸出
Hibernate:
select
user0_.id as id1_0_0_,
user0_.name as name2_0_0_,
user0_.password as password3_0_0_
from
user user0_
where
user0_.id=?
name:test
- 測試方法中並沒有做update操作,但是執行了update操作,是因為get方法獲取的user是持久化對象,可以自動更新數據庫
- 如果setName方法設置的值和數據庫裏的name一樣,也不會執行update操作
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。