程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> 初學者想學Hibernate,初級基礎教程

初學者想學Hibernate,初級基礎教程

編輯:JAVA編程入門知識

  Hibernate理論基礎

  1. 什麼是hibernate?
  2. hibernate的知識內容
  3. 什麼是對象持久化?對象持久化有什麼用?(解決的問題)
  4. 如何對象持久化?
  5. 如何用數據庫的方法做對象持久化?
  6. ORM(對象關系映射)是什麼?有什麼作用?
  7. ORM從對象到表所要考慮的問題
  8. 什麼是ORM框架?有什麼用?
  9. 使用hibernate的方法做對象持久化的工作,程序員應該怎麼做?
  10. hibernate有什麼用?
  11. 程序員和hibernate的整體工作流程

  什麼是hibernate:

  持久化的框架,屬於設計方面的內容,類庫,用來做對象持久化的,什麼是對象持久化呢?

  Hibernate的知識內容:

  語法部分(類庫)

  程序設計思想,也就是持久層的設計

  什麼是對象持久化?對象持久化有什麼用?(解決的問題):

  發現問題:

  程序設計的架構: 表現層—業務層—持久層—數據庫層,其中表現層和業務層是JVM來執行,應用程序會產生許多的對象,假如斷電了,對象就消失了,也就是說在內存中的對象是不穩定的,狀態不能持久

  發現問題:

  將一個對象從A電腦復制到B電腦,如何做到呢?

  那麼有三種方法解決上面的問題:
  1. 序列化: 通過網絡傳遞,或者硬盤共享
  2. 存儲到數據庫中,誰想用,從數據庫中拿
  3. EJB Entity Bean(實體Bean)

  序列化的方法比較死板:假如當一個對象的結構比較復雜的時候,我們這時只需要一部分內容,沒有辦法,只能整個寫入到文件,整個讀取
  序列化的缺點: 不能檢索,不能分離一個對象,不方便共享
  所以說第一種方法只能用於做臨時的持久化,簡單的傳輸,但不適合復雜的持久化工作

  第二種方法(數據庫持久化):檢索方便,分布式共享,永久數據

  總結:
  什麼是對象持久化: 對象持久化就是把內存中的對象永久的保存起來,保護對象的狀態,方便使用
  對象持久化有什麼用: 1.解決掉電的問題 2.共享方便 3.保證對象安全檢索方便

  如何對象持久化:
  1. 對象序列化
  2. 數據庫(JDBC,EJB,Hibernate)

  如何用數據庫的方法做對象持久化:
  1. JDBC
  發現問題: 需要做大量的工作,難度大
  2. EJB
  使用的是其中的一個功能來做持久化,解決了使用JDBC方法的的大量工作的問題
  發現問題: EJB是重量級的組件,要使用它,有兩個問題 1.成本 2.性能

  發現問題: 以上兩種方式還有個共同的問題,對象不是簡單存儲在數據庫中的,比如多態的特點就不能處理 A b=new B(); B為A的子類

  3. Hibernate
  解決了以上的所有問題,作用:1.不用做大量的工作 2.移植性能好 3.提高了代碼的質量,簡單 4.檢索共享重用成本調試

  ORM(對象關系映射)是什麼?有什麼作用?
  發現問題:
  Java中的對象的屬性類型和數據庫中的字段類型是不一樣的,那麼如何來存儲java中的對象呢?這就需要做對象關系的映射,也就是ORM
  什麼是ORM: 將內存中的對象和數據庫做轉化,這樣就實現了java與數據庫之間的訪問等功能

  ORM從對象到表所要考慮的問題:
  Orm的復雜問題:
  1. 數據庫如何保證對象的唯一性:在內存中,兩個對象屬性值都一樣,但是內存地址不一樣,可以做區分,但是在數據庫中如何分辨呢?
  2. 繼續關系如何轉化
  3. 集合如何映射呢?

  什麼是ORM框架?有什麼用?
  就是一個類庫,通過這個類庫完成持久化層的設計

  使用hibernate的方法做對象持久化的工作,程序員應該怎麼做?
  1. 將ORM方案定下來,就是類到數據庫的轉化 2.利用hibernate生成代碼
  hibernate有什麼用?
  1. 完成jdbc的代碼
  2. 治理持久化對象的狀態
  3. 提供一個查詢的API

  程序員和hibernate的整體工作流程
  程序員:
  1. 設計ORM方案
  2. 寫配置文件
  3. 調用Hibernate的API,向Hibernate發出命令
  hibernate:
  4. 讀配置文件
  5. 生成jdbc代碼
  6. 執行

  Hibernate簡單實例
  Hibernate語法:
  作用: 數據庫的增刪改查 HQL面向對象的查詢語句

  大致步驟:
  1. 設置環境 類庫
  2. 定義映射
  A 定義映射的實體po
  B 建立數據庫表
  C 寫XML配置文件(表,數據庫)
  3. 調用Hibernate API
  A 治理po的狀態(增刪改,恢復po狀態)
  B 檢索(查詢)

  Hibernate第一個簡單的實例: 引例(frisHbn包)
  1. 設置環境
  hibernate配置環境需要的資源
  Hibernate的jar包: lib.zip dtd.zip: dtd.zip可以不設置
  2. 定義映射
  建立項目:
  bussiness包: entity包 Biz包業務
  client包: 測試
  util包: 工具

  先寫持久化類: 以花為實體,建立花類,並且建立數據庫表
  /**
  * 建表語句:
  * CREATE TABLE T_FRUIT(
  FID NUMBER(10) PRIMARY KEY,
  
   NAME VARCHAR(20) NOT NULL,
  COMMENTS VARCHAR(50),
  PRICE NUMBER(5) NOT NULL
  );
  */
  package YUChen.fristHbn.business.entity;
  //持久化類(花類),注重因為采用的是hilo的方式獲得id,所以需要有setid的方法
  public class Fruit {

  private Integer fid;//hibernate中的id不能識別int
  private String name;
  private String comments;
  private int price;

  public Fruit() {
  super();
  }

  public Fruit(String name, String comments, int price) {
  super();
  this.name = name;
  this.comments = comments;
  this.price = price;
  }

  public String getComments() {
  return comments;
  }
  public void setComments(String comments) {
  this.comments = comments;
  }

  public Integer getFid() {
  return fid;
  }
  public String getName() {
  return name;
  }
  public void setName(String name) {
  this.name = name;
  }
  public int getPrice() {
  return price;
  }
  public void setPrice(int price) {
  this.price = price;
  }

  public void setFid(Integer fid) {
  this.fid = fid;
  }

  }

  使用hilo的方式獲得id:
  建表語句:
  CREATE TABLE T_HILO(HILO_ID NUMBER(10));
  INSERT INTO T_HILO VALUES(1);

  寫hibernate的連接數據庫的配置文件:
  <?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>
  <property name="show_sql">true</property>
  <property name="connection.driver_class">Oracle.jdbc.driver.OracleDriver</property>
  <property name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:name</property>
  <property name="connection.username">scott</property>
  <property name="connection.passWord">tiger</property>
  <property name="connection.isolation">2</property>
  <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
  <mapping resource="Yuchen/fristHbn/business/entity/Fruit.hbm.xml"/>
  </session-factory>
  </hibernate-configuration>

  寫映射配置文件:
  <?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="Yuchen.fristHbn.business.entity">
  <class name="Fruit" table="T_FRUIT">
  <id name="fid" column="fid">
  <generator class="hilo">
  
   <param name="table">t_hilo</param>
  <param name="column">hilo_id</param>
  </generator>
  </id>
  <property name="name" column="name" />
  <property name="comments" column="comments"></property>
  <property name="price" column="price"></property>
  </class>
  </hibernate-mapping>
  A. 類名—表名
  B. id—id 獲得id的方式 具體信息(如: hilo的表名和字段)
  C. 屬性—字段

  使用hibernate API(FruitManager.java):
  package Yuchen.fristHbn.business.Biz;
  //業務邏輯類:負責增刪改查通過使用hibernate API進行
  import org.hibernate.Session;
  import org.hibernate.SessionFactory;
  import org.hibernate.Transaction;
  import org.hibernate.cfg.Configuration;

  import Yuchen.fristHbn.business.entity.Fruit;

  public class FruitManager {
  public void insert(Fruit fruit){
  Configuration config=new Configuration();
  config.configure();//讀配置文件
  SessionFactory sf=config.buildSessionFactory();//得到工廠
  Session session=sf.openSession();//得到session
  Transaction tt=session.beginTransaction();//檢查事務開啟
  session.save(fruit);//存儲insert
  tt.commit();//提交
  session.close();//關閉資源
  }
  }

   

  寫測試類: 插入一個對象到數據庫中
  /**
  * 知識點:
  * hibernate基礎:練習語法部分API和簡單的映射關系
  * 程序目標:
  * 使用hibernate方法將對象進行持久化
  * 實現數據庫的增刪改查
  * API:
  * 1.Configuration:這個類負責讀取XML文檔(映射配置文件)
  * configure():讀xml
  * buildSessionFactory():創建一個生產session對象的工廠,其實是再次檢查
  * 因為hibernate和jdbc不一樣,jdbc是假如不手動設置開啟事務,那它
  * 就是馬上執行sql的,hibernate的不會馬上執行,是事務提交後執行
  * 默認情況下就是打開事務的狀態,這裡只是再檢查以下
  * 2.SessionFactory:負責生產session對象
  * openSession():創建一個session
  * 3.Session類:這個是主要的類,負責增刪改查,開啟事務等
  * beginTransaction():產生一個事務對象(Transaction)
  * save():增加相當於操作sql中的insert語句
  * 4.Transaction類:負責治理事務的
  * commit():提交一個事務
  *
  */
  package Yuchen.fristHbn.client;

  import Yuchen.fristHbn.business.Biz.FruitManager;
  import Yuchen.fristHbn.business.entity.Fruit;

  public class Test {

  public static void test1(){
  Fruit fruit=new Fruit("lisi","hello",100);
  // fruit.setName("zhangsan");
  // fruit.setComments("hello");
  // fruit.setPrice(100);

  FruitManager fm=new FruitManager();
  fm.insert(fruit);
  }
  public static void main(String[] args) {
  // TODO 自動生成方法存根
  Test t=new Test();
  t.test1();
  }

  }

  hibernate API(一):
  Configuration: 讀取配置文件信息用來初始化的
  SessionFactory: 重量級對象,特點:消耗資源大,線程是安全,所以可以被共享
  上面兩個對象只實例化一個就行了,都是用於初始化的
  Session: 線程是不安全的,所以要避免多個線程共享它,是輕量級的對象,使用後關閉

  Session對象的狀態:
  順態: 還沒有被持久化,也就是說數據庫中沒有該對象的記錄,並且Session中的緩沖區裡沒有這個對象的引用
  持久態: 在數據庫中有該對象的記錄,並且在session中的緩沖區裡有這個對象的引用,和順態正好相反
  游離態: 在數據庫中有記錄,但是不在session的緩沖區裡

  對象狀態的轉換:
  做一個工具類,將hibernate中重復的代碼包裝起來:
  package Yuchen.fristHbn.util;
  //生產session對象的工具類
  import org.hibernate.Session;
  import org.hibernate.SessionFactory;
  import org.hibernate.cfg.Configuration;

  public class HbnUtil {
  
   private static SessionFactory sf;
  static{
  sf=new Configuration().configure().buildSessionFactory();
  }

  public static Session getSession(){
  return sf.openSession();
  }
  }

  完善FruitManager類:
  package Yuchen.fristHbn.business.Biz;
  //業務邏輯類:負責增刪改查通過使用hibernate API進行
  import org.hibernate.Session;
  import org.hibernate.SessionFactory;
  import org.hibernate.Transaction;
  import org.hibernate.cfg.Configuration;

  import Yuchen.fristHbn.business.entity.Fruit;
  import Yuchen.fristHbn.util.HbnUtil;

  public class FruitManager {
  public Integer insert(Fruit fruit){
  Session session=HbnUtil.getSession();//通過工具更方便了
  Integer id=null;
  // Configuration config=new Configuration();
  // config.configure();//讀配置文件
  // SessionFactory sf=config.buildSessionFactory();//得到工廠
  // Session session=sf.openSession();//得到session
  Transaction tt=session.beginTransaction();//檢查事務開啟
  id=(Integer)session.save(fruit);//存儲insert
  tt.commit();//提交
  session.close();//關閉資源
  return id;
  }

  public Fruit selectId(Integer id){
  Session session=HbnUtil.getSession();
  Transaction t=session.beginTransaction();
  Fruit fruit=(Fruit)session.get(Fruit.class, id);
  t.commit();
  session.close();
  return fruit;
  }

  public void remove(Fruit fruit){
  Session session=HbnUtil.getSession();
  Transaction t=session.beginTransaction();
  session.delete(fruit);
  t.commit();
  session.close();
  }
  }

  測試對象狀態的轉換:
  /**
  * 知識點:
  * hibernate基礎:練習語法部分API和簡單的映射關系
  * 程序目標:
  * 使用hibernate方法將對象進行持久化
  * 實現數據庫的增刪改查
  * API:
  * 1.Configuration:這個類負責讀取XML文檔(映射配置文件)
  * configure():讀xml
  * buildSessionFactory():創建一個生產session對象的工廠,其實是再次檢查
  * 因為hibernate和jdbc不一樣,jdbc是假如不手動設置開啟事務,那它
  * 就是馬上執行sql的,hibernate的不會馬上執行,是事務提交後執行
  * 默認情況下就是打開事務的狀態,這裡只是再檢查以下
  * 2.SessionFactory:負責生產session對象
  * openSession():創建一個session
  * 3.Session類:這個是主要的類,負責增刪改查,開啟事務等
  * beginTransaction():產生一個事務對象(Transaction)
  * save():增加相當於操作sql中的insert語句
  * 4.Transaction類:負責治理事務的
  * commit():提交一個事務
  * test1():測試插入的功能
  * test2():測試數據同步更新的功能
  * test3():測試saveOrUpdate()
  * test4():測試clear()和flush()
  */
  package Yuchen.fristHbn.client;

  import org.hibernate.Session;
  import org.hibernate.Transaction;

  import Yuchen.fristHbn.business.Biz.FruitManager;
  import Yuchen.fristHbn.business.entity.Fruit;
  import Yuchen.fristHbn.util.HbnUtil;

  public class Test {

  public void test1(){
  Fruit fruit=new Fruit("lisi","hello",100);
  // fruit.setName("zhangsan");
  // fruit.setComments("hello");
  // fruit.setPrice(100);

  FruitManager fm=new FruitManager();
  fm.insert(fruit);
  }

  public void test2(){
  //測試同步更新的功能
  Fruit fruit=new Fruit("meigui","hongse",70);//順態
  FruitManager fm=new FruitManager();
  Fruit fruit2=new Fruit();

  Integer id=fm.insert(fruit);
  
   fruit2=fm.selectId(id);
  System.out.println(fruit2.getFid());
  System.out.println(fruit2.getName());

  fruit.setName("ziluolan");//這裡修改了對象
  fruit2=fm.selectId(id);
  System.out.println(fruit2.getFid());//但是結果沒有更新
  System.out.println(fruit2.getName());
  //因為fruit在Integer id=fm.insert(fruit);後變成游離態了
  //也就是說只有持久態才能實現同步更新
  System.out.println(fruit.getFid());
  System.out.println(fruit.getName());
  }

  public void test3(){
  Session session=HbnUtil.getSession();
  Transaction t=session.beginTransaction();
  Fruit fruit=new Fruit("ziluolan","lanse",100);//順態
  Fruit fruit2=new Fruit();
  FruitManager fm=new FruitManager();
  session.save(fruit);//fruit在運行完此句後變為游離態
  fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
  //從數據庫讀並打印出來
  System.out.println(fruit2.getFid()+":"+fruit2.getName());

  session.saveOrUpdate(fruit);//假如該對象為游歷態就更新數據庫update
  //否則就是順態,增加insert
  fruit2=(Fruit) session.get(Fruit.class, fruit.getFid());
  //saveOrUpdate後再從數據庫讀並打印出來
  System.out.println(fruit2.getFid()+":"+fruit2.getName());
  //兩個打印結果一樣,saveOrUpdate方法判定假如id為null,就
  //順態,否則就是游離態
  t.commit();
  session.close();
  }

  public void test4(){
  Session session=HbnUtil.getSession();
  Transaction t=session.beginTransaction();
  Fruit fruit=new Fruit("guihua","fense",300);//順態
  Fruit fruit2=new Fruit();
  session.saveOrUpdate(fruit);//執行insert因為對象為順態
  // session.flush();
  session.clear();//fruit變成游離態了,並且不會執行insert語句
  //因為hibernate不是馬上執行sql,而是等t.commit()提交事務
  //後才執行,clear後,對象為游離態

  session.saveOrUpdate(fruit);//這裡驗證上面的話,執行update
  //做個select查看一下,可以證實,因為clear後,沒有馬上執行
  //sql語句,所以表裡沒有數據,這裡update也沒有用,所以表中
  //一個對象也沒插入,但是假如加入flush()刷新就是馬上執行sql了

  t.commit();
  session.close();
  }
  public static void main(String[] args) {
  // TODO 自動生成方法存根
  Test t=new Test();
  // t.test1();
  // t.test2();
  // t.test3();
  t.test4();
  }

  }

  hibernate API(二):
  flush(): 從上面的例子可以看出,flush是刷新session的緩沖區,並執行裡面的命令
  flush()的事務治理模式: flushMode()裡面有三個常量,可以用數字來表示
  Load(): 另一種讀取數據的方法,和get的區別是: 1.異常處理: load有異常處理,get沒有,它返回null,2.get從數據庫讀數據,load可能去讀緩沖區

  事務的隔離級別:
  在hibernate的數據庫配置文件中設置
  數字1為可以髒讀,數字2為不能,這個是最常用的

  鎖機制:
  避免並發沖突,在數據庫中寫數據是自動加鎖的,讀一般不加,有悲觀鎖和樂觀鎖
  樂觀鎖是可以是hibernate程序自己加
  實現樂觀鎖: 引例(hbn2包)
  步驟:
  1. 在表中加個version字段
  2. 在持久類裡加個version屬性
  3. 配置文件<version name=”versopm”> 每存一次值加1

  引例:hbn2包

  復雜的映射:
  1. 基數關系映射
  2. 繼續關系映射
  3. 組件關系映射
  4. 集合映射

  基數關系的映射—one to one:
  基數關系的映射需要考慮的問題:
  1. 數量問題
  2. 方向問題
  在one to one的關系中,我們有兩種方法可以體現類與類之間的關系
  1. 共享主鍵
  2. 外鍵唯一
  引例: Joto包-此包引用了fristHbn包

  建立與Fruit類有一對一關系的類:
  我們認為一個花有一個產地,一個產地生產一種花,所以要建立產地類
  package Yuchen.Joto.business.entity;
  //花的地址類
  //問題:為什麼不能在構造函數中寫Fruit?因為生成對象後要持久化
  //這個對象,但是數據庫的表中不能插入另一個類的值,寫上null又不
  //大合適,所以就去掉它
  public class Address {
  private Integer aid;
  
   private String nation;
  private String postcode;
  private Fruit fruit;
  public Address() {

  }
  public Address(String nation, String postcode) {
  super();
  this.nation = nation;
  this.postcode = postcode;
  }
  public Integer getAid() {
  return aid;
  }
  public void setAid(Integer aid) {
  this.aid = aid;
  }
  public Fruit getFruit() {
  return fruit;
  }
  public void setFruit(Fruit fruit) {
  this.fruit = fruit;
  // fruit.setAddress(this);
  }
  public String getNation() {
  return nation;
  }
  public void setNation(String nation) {
  this.nation = nation;
  }
  public String getPostcode() {
  return postcode;
  }
  public void setPostcode(String postcode) {
  this.postcode = postcode;
  }

  }

  修改Fruit類:
  package Yuchen.Joto.business.entity;
  //持久化類(花類),注重因為采用的是hilo的方式獲得id,所以需要有setid的方法
  public class Fruit {

  private Integer fid;//hibernate中的id不能識別int
  private String name;
  private String comments;
  private int price;
  private Address address;//一朵花對應一個地址

  public Fruit() {
  super();
  }

  public Fruit(String name, String comments, int price) {
  super();
  this.name = name;
  this.comments = comments;
  this.price = price;
  }

  public Address getAddress() {
  return address;
  }

  public void setAddress(Address address) {
  this.address = address;
  address.setFruit(this);//因為當你給一個花設置產地的時候
  //該產地也有了花
  }

  public String getComments() {
  return comments;
  }
  public void setComments(String comments) {
  this.comments = comments;
  }

  public Integer getFid() {
  return fid;
  }
  public String getName() {
  return name;
  }
  public void setName(String name) {
  this.name = name;
  }
  public int getPrice() {
  return price;
  }
  public void setPrice(int price)


 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved