三、hibernate中持久化類的使用
阿新 • • 發佈:2018-12-20
持久化對象 console image 持久 就是 ssi seq sybase 內存
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操作
三、hibernate中持久化類的使用