hibernate基礎知識
Hibernate框架知識
1、理論hibernate overview
2、映射
mapping entity
mapping entity associations-1
mapping entiity associations-2
3、狀態管理
working with persistent Objects
4、其他問題
事務
HQL
Hibernate是什么東西?功能是什么?起什么作用?其結構和工作原理是什么?
Hibernate的結構和工作原理
O-----〉R
轉換
對象持久化的工具------這也是最核心的部分;
怎么把對象轉到數據庫里
為什么要用hibernate做對象持久化
一、什么叫對象持久化?
簡單的說,對象持久化就是將內存中的對象狀態存在的數據轉存到外部持久設備。
在適當的時候可以將持久設備中的數據恢復到內存對象狀態下的數據
O------------存----------->R
<-------------恢復---------
內存 持久設備
(是可逆的過程)
oracle---甲骨文---龜文-----持久化
二、為什么要持久化
1、物理上的原因
內存不能持久化
內存容量有限
內存主要是為了運算而用的,夠算就行,而不是為了存儲數據而用的!!!!
總線 32位-64位-128位
2、業務上的原因
信息流動----帶動人流動-----帶動 物流=====〉信息先導性
所有的軟件都是以數據為中心的,數據-----信息00
信息高速公路-----帶動經濟發展
數據最關鍵不是加工而是流動起來,搜集、存取、分析、統計
共享(流動)=====+++++
管理(安全、有效、備份)
大規模檢索
結論:對于一個企業的數據來說,對象持久化是必須要做的
三、怎么樣進行對象持久化(java平臺)
1、對象序列化 x-------把對象搞到硬盤上去
只是個別對象序列化------序列化之后變成一個二進制文件------
對于對象序列化之后的文件來說是無法檢索的,必須全部再恢復到內存中之后再進行檢索
不適合存儲海量的數據
對象有空間結構,對象序列化就是把其空間結構變成二進制數值
2、DB 必須用DB-------真正的對象持久化
四、怎么樣使用DB進行對象持久化(java平臺)
1、jdbc是基礎,利用jdbc可以存儲
優點:功能完備、理論上效率最高、接口密度細;主要是干些細活
缺點:代碼量大(可以增加人手)、開發難度大
很少直接拿jdbc來進行對象持久化
2、EJB entity Bean 有點過時了,但現在大量的程序還在運轉
優點:封裝了jdbc
缺點:采取了一個重量級的解決方案
成本高
維護工作量大
EJB功能太多,其中持久化為其最弱的一塊
更復雜的api
不能在服務器之外進行測試
組件。必須得實現指定的接口,EJB服務器才能管理使用它
技術上的:是以服務器為核心
商業上的:捆綁銷售
3、輕量級的ORM框架Hibernate
優點:輕量級-----把EJB中持久化這部分單獨拿出來,和EJB中一樣都是封裝JDBC,但是設計思路不一樣
做一個單一的類庫
專業
持久對象是一個pojo--〉純oo
功能是可裁減的可擴充的開源的
成本低
封裝了jdbc,提供了一個更簡單的api
缺點:
功能完備性差(不如JDBC強,但比EJB強),主要是批量更新
也就是說一般情況下選擇hibernate來做,部分采用JDBC來選擇。(Hibernate大部分功能都可實現,只有部分需要JDBC來完成)
五、Hibernate的工作原理和結構
工作原理:封裝jdbc來完成對象持久化;就是替代JDBC來完成持久化
hibernate的結構與jdbc的結構
內存中 數據庫中
O <------------JDBC--------------->R
| \
| \------------------|映射(要考慮業務的那個對象與數據庫的字段有關系)
APPLICATION <-------- PROGRAMMER
為什么呢?因為JDBC這種結構,讓程序員太累,需要考慮業務的哪個對象與數據庫哪個表的哪個字段有關系(映射)
內存中 _hibernate 數據庫中
O <--------|--JDBC--|------------->R
------ \
| \ --------------映射文件XML
| \------------------|映射(要考慮業務的那個對象與數據庫的字段有關系)
APPLICATION <-------- PROGRAMMER
主要的任務:
1、首要映射說清楚-------映射文件
2、下指令----API
O---------| JDBC |-----------------R
| ------- |生成jdbc
HIBERNATE參考-----|
| |映射文件|XML
|命令 |
app------ PROGRAMMER
持久化-----類比成搬家
復雜的地方在映射文件
po講解----po持久類;pojo;編碼規范
1、oid(對象的唯一標識)--中性的。對象有一個唯一的屬性,表里需要一個主鍵。
為什么要用一個oid?
持久對象有一個唯一標識符,對應表里有一個主鍵。
hibernate對jdbc的管理,主要是靠這個主鍵
為什么必須是中性的?唯一標識符;增刪改查都要這個主鍵
主鍵的產生不統一;
業務一發生變化,號碼的結構可能也會發生變化
Hibernate不了解業務結構,而oid由hibernate負責產生和管理
我們選擇的oid和業務無關。
2、要有一個空的構造方法(重點)
因為有參數的構造方法,hibernate不能用
類x有m int,n int屬性-----〉自然而然肯定有一個構造方法x(int,int);
hibernate從數據庫表中讀出
num num
100 200
(100,200),那么hibernate肯定不能識別出m,n呢
那么hibernate怎么來識別呢?
hibernate不能使用有參數的構造方法,通過反射機制必須使用無參構造方法
new x();
x.setM();---->x.setM(100);
x.setN();---->x.setN(200);
3、setter/getter (由于屬性都是私有的,所以必須有setter和getter方法)
比如說有一個賬戶對象Acct()
Acct acct=new Acct();
JDBC訪問的主要代碼
Con= //連接到數據庫
con.setAutoConnction();
sql="insert into"value(???)
ps=---------;
ps.setXXX(1,--);
ps.setXXX(2,--);
ps.executeUpdate();
con.commit();
hibernate訪問主要代碼
Session =
session.begin();
session.save(acct);
session.commit();
session{--------hibernate
save
delete
update
create}
HIBERNATE的api簡單
映射怎么寫?-----
步驟:
0環境
1po
2映射文件
3schema
4test(hibernate api)類
環境:
1、把hibernate類庫導入到開發環境中---〉eclipse工程中
選中工程
java Build Path
add Library
user library--new
add JARs
import導入
2、兩個xml文件需要寫
映射文件(類,表之間的映射關系)
配置(可以有多個,db連接信息)---提供數據庫的連接信息以及hibernate自身的一些信息
import導入映射文件和配置文件
準備2個模板,避免寫錯了
注意:盡量不要混合使用不同版本的jar包,所以一定要考察好使用的版本的功能
lib.zip---類庫 hibernate3.jar核心庫,其他都是輔助庫,
dtd.zip
template.zip
ojdbc.jar
mysql.jar
接下來我們要寫程序了:
第一步:構建一個po持久類
package com.newxyz.hbn1.biz.entity;
public class Account {
//持久類
private Long oid; //由hibernate自動生成oid,表里面必須有這個字段,類必須有這個屬性 ,
//切記oid屬性為Long
private String acctNo; //帳戶
private double bal; //余額
public Account() { //空的構造器;為什么必須用空的構造器呢?
//有參數的構造器,hibernate不能用
}
public Account(String acctNo, double bal) {
super();
//必須再增加一個有參數的構造器,為什么呢?
//類本身初始化要使用
//但是不能包含oid----,是由hibernate來提供。
this.acctNo = acctNo;
this.bal = bal;
}
public void deposite(double amount){ //存款
bal=bal+amount;
}
public void withdraw(double amount){ //取款
bal=bal-amount;
}
//公開訪問方法getXxxx,setXxxx
public Long getOid() {
return oid;
}
public void setOid(Long oid) {
this.oid = oid;
}
public String getAcctNo() {
return acctNo;
}
public void setAcctNo(String acctNo) {
this.acctNo = acctNo;
}
public double getBal() {
return bal;
}
public void setBal(double bal) {
this.bal = bal;
}
}
第二步:編寫映射文件
映射文件的編碼要求
1、1個映射文件映射一個持久類;是一種習慣;
2、映射文件名稱與持久類名稱保持一致,如
Account.java Account.hbm.xml
hbm====hibernate mapping
3、映射文件要與其映射的持久類放在同一個包路徑下
映射文件特定的模板:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.newxyz.hbn1.biz.entity"> //package類似于java中的import
<class name="" table="">
<id name="" column="">
<generator class="" />
</id>
<property name="" column=""></property>
</class>
</hibernate-mapping>
單表映射 (類映射表;類屬性映射字段)
類.屬性映射表的字段------>因為兩者都是由同一實體得來
Account.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.newxyz.hbn1.biz.entity">
<!--//package類似于java中的import,根元素;在根標記里面有一個package可以用;-->
<class name="Account" table="t_acct">
<id name="oid" column="OID">
<generator class="hilo">
<param name="talbe">t_hilo</param>
<param name="column">hi</param>
<!--
表名
表里面字段的名字
意思是當hibernate讀取該映射文件時,一旦看見generator class=“hilo”,從表t_hilo中查找字段為hi中取一個值。
-->
</generator>
</id>
<property name="acctNo" column="ACCTNO"/>
<property name="bal" column="BAL"/>
</class>
</hibernate-mapping>
<id name="" column="">
<generator class="hilo" >
<!-- 需要指定表名和字段名-->
<param name="table">t_hilo</param>
<param name="column">hi</param>
</generator>
</id>
OID是由hibernate自動生成,不是隨便聲稱,要有唯一性
生成值的算法有好多種《查詢百度》
怎么樣每次產生的id是不一樣的呢?
一般用計數器
比如有一個程序自己維護這個計數器,計數器的數字必須放在數據庫中才行。
必須要考慮到程序關閉,計數器清0的情況。計數器持久化
hilo算法 高低位算法
從公有計數器取一個高位值,私有計數器自動生成一個低位值。
如全球電話號碼 010-87654321
020-87654321
3、接下來從數據庫里面建表
create table t_acct(
OID number(18) primary key,
ACCTNO varchar(30) not null,
BAL number(12,2) not null);
create table t_hilo(hi number(18) primary key);
insert into t_hilo values(1);//必須有一行,要不hibernate取不到值就會報錯。
commit;
4、修改hibernate.cfg.xml配置文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory><!--這些配置信息主要是通過session工廠來識別的-->
<property name="show_sql">true</property><!--讓hibernate運行期間,將其運行的SQL語句顯示到console上-->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@192.168.0.23:1521:tarena</property>
<property name="connection.username">openlab</property>
<property name="connection.password">open123</property>
<property name="connection.isolation">2</property><!--隔離級別,防止臟讀-->
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property><!--dialet方言,地方話:假設是mysql的話應該是org.hibernate.dialect.MySQLDialect-->
<mapping resource="com/newxyz/ebank/biz/entity/Account.hbm.xml"/>
</session-factory>
</hibernate-configuration>
5、寫一個測試類test1.java
package com.newxyz.hbn1.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.newxyz.hbn1.biz.entity.Account;
public class test1 {
public static void main(String[] args) {
Account acct=new Account("a001",6000.0);
//創建一個帳戶對象,存起來
Configuration cfg=new Configuration();
cfg.configure();
//加載配置文件
//Configuration cfg=new Configuration().configure();
SessionFactory sf=cfg.buildSessionFactory();
Session s=sf.openSession();
//加載SessionFactory,通過SessionFactory來創建Session
try {
s.beginTransaction();
s.save(acct);
s.getTransaction().commit();//事務跟數據庫沒關系,只跟交易有關系
} catch (HibernateException e) {
e.printStackTrace();
s.getTransaction().rollback();
}finally{
s.close();
}
}
}