轉Hibernate3.0

Hibernate3.0
預備知識:
Core Java
JDBC
SQL
 
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) {
            this.price = price;
      }
 
      public void setFid(Integer fid) {
            this.fid = fid;
      }
     
}
 
爲地址實體類建表:
//oto共享主鍵方式
create table t_address(
      aid number(10) primary key,
      nation varchar2(30) not null,
      postcode varchar2(10) not null,
      constraint address_fruit foreign key(aid) references T_FRUIT(fid)
);
注意建表的方式不同,所對應的映射文件也有些區別
 
共享主鍵方式的映射文件:
<?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.Joto.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>
            <one-to-one name="address" cascade="all" />
      </class>
      <class name="Address" table="t_address">
           <id name="aid" column="aid">
                 <generator class="foreign">
                       <param name="property">fruit</param>
                 </generator>
            </id>
            <property name="nation" column="nation"></property>
            <property name="postcode" column="postcode"></property>
            <one-to-one name="fruit" constrained="true"></one-to-one>
      </class>
</hibernate-mapping>
 
思路:
寫類—表,類中的屬性—字段,類關係(從數據庫的角度出發)
 
外鍵唯一的方式:建表:
create table t_address(
      aid number(10) primary key,
      nation varchar2(30) not null,
      postcode varchar2(10) not null,
      fid number(10) not null unique,
      constraint address_fruit foreign key(fid) references T_FRUIT(fid)
);
配置文件中修改<one-to-one name="fruit"
constrained="true"></one-to-one>爲<many-to-one name="fruit" column="fid" unique="true" cascade="all" />
 
client程序:
/**
 * 知識點:
 * 基數關係映射:one to one
 * 程序目標:
 * 1.寫持久類,建立持久類之間的關係
 * 2.定義映射關係,爲po建表:兩種建表方式
 * 第一種:共享主鍵
 * 第二種:外鍵唯一
 * 3.寫映射文件
 * 共享主鍵情況下映射文件的寫法:
 * A.主鍵方:<one-to-one name="引用類型變量名" cascade="all">
 * B.外鍵方:<one-to-one name="引用類型變量名" constrained="true">
 * 外鍵唯一情況下映射文件的寫法:
 * A.主鍵方:<one-to-one name="引用類型變量名" cascade="all">
 * B.外鍵方:<many-to-one name="引用類型變量名" column="fid" unique="true" cascade="all" />
 */
package Yuchen.Joto.client;
 
import org.hibernate.Session;
import org.hibernate.Transaction;
 
import Yuchen.Joto.business.entity.Address;
import Yuchen.Joto.business.entity.Fruit;
import Yuchen.Joto.util.HbnUtil;
 
public class Test {
     
      public void test1(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
           Fruit fruit=new Fruit("掉藍","綠色",260);
            Address arddess=new Address("中國","崛起");
            fruit.setAddress(arddess);
            session.save(fruit);
            t.commit();
            session.close();
      }
     
      public static void main(String[] args) {
           // TODO 自動生成方法存根
           Test t=new Test();
            t.test1();
      }
 
}
 
基數關係的映射(one to many):
引例:Jotm包
我們認爲一種花有多個產地:
建立花類:
package Yuchen.Jotm.business.entity;
//花類
import java.util.HashSet;
import java.util.Set;
 
public class Fruit {
      private Integer fid;
      private String name;
    private String comments;
   private int price;
    private Set addresses = new HashSet();//一種花有多個產地
      public Fruit() {
            super();
      }
      public Fruit(String name, String comments, int price) {
            super();
            this.name = name;
            this.comments = comments;
            this.price = price;
      }
     
      public void setAddress(Address address) {
            addresses.add(address);
            address.setFruit(this);
      }
      public Set getAddresses() {
            return addresses;
      }
      public void setAddresses(Set addresses) {
            this.addresses = addresses;
      }
      public String getComments() {
            return comments;
      }
      public void setComments(String comments) {
            this.comments = comments;
      }
      public Integer getFid() {
            return fid;
      }
      public void setFid(Integer fid) {
            this.fid = 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;
      }
   
}
 
建立產地類:
package Yuchen.Jotm.business.entity;
 
//地址類
public class Address {
         private Integer aid;
         private String nation;
         private String postcode;
         private Fruit fruit;//一個地址對應一種花
      public Address() {
            super();
      }
      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;
      }
      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類:
create table T_FRUIT_many2one(
   FID number(10) PRIMARY KEY,
   NAME VARCHAR2(20) NOT NULL,
   COMMENTS VARCHAR2(50),
   PRICE number(5) NOT NULL
);
 
Address類:
這個是多的一方,所以他的外鍵的值要引用Fruit類的主鍵值
CREATE TABLE T_ADDRESS_many2one(
   AID number(10) PRIMARY KEY,
   NATION VARCHAR2(30) NOT NULL,
   POSTCODE VARCHAR2(10) NOT NULL,
   AFID number(10) NOT NULL,
   CONSTRAINT ADDRESS_FRUIT_many2one FOREIGN KEY(AFID)
   REFERENCES T_FRUIT_many2one(FID)
);
 
寫映射配置文件:
<?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.Jotm.business.entity">
      <class name="Fruit" table="T_FRUIT_many2one">
           <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>
          <set name="addresses" inverse="true" cascade="all">
                 <key column="afid"></key>
                 <one-to-many class="Address"></one-to-many>
            </set>
      </class>
      <class name="Address" table="t_address_many2one">
           <id name="aid" column="aid">
                 <generator class="hilo">
                     <param name="table">t_hilo</param>
                       <param name="column">hilo_id</param>
                 </generator>
            </id>
            <property name="nation" column="nation"></property>
          <property name="postcode" column="postcode"></property>
            <many-to-one name="fruit" column="afid" cascade="all"></many-to-one>
      </class>
</hibernate-mapping>
 
client類:
/**
 * 知識點:
 * 基數關係映射:one to many
 * 程序目標:
 * 映射文件的寫法:
 * 1.主鍵方:
 * <set name="引用類型的變量" inverse="true" cascade="all">
 * <key column="外鍵名">
 * <one-to-many class="外鍵的類名"></one-to-many>
 * 2.外鍵方:
 * <many-to-one name="引用類型的變量" column="外鍵名" cascade="all">
 */
package Yuchen.Jotm.client;
 
import Yuchen.Jotm.business.Biz.FruitManager;
import Yuchen.Jotm.business.entity.Address;
import Yuchen.Jotm.business.entity.Fruit;
 
public class Test {
     
      public static void main(String[] args){
            FruitManager fm=new FruitManager();
            Address address1=new Address("北京","0000");
            Address address2=new Address("上海","000340");
           Fruit fruit=new Fruit("玫瑰","紅色",2000);
            fruit.setAddress(address1);
            fruit.setAddress(address2);
            fm.insert(fruit);
      }
}
 
基數關係的映射(many to many):
我們把花和產地看爲多對多的關係:
引例:Jmtn包
修改產地類:
package Yuchen.Jmtn.business.entity;
 
import java.util.HashSet;
import java.util.Set;
 
//產地類
public class Address {
         private Integer aid;
         private String nation;
         private String postcode;
         private Set fruits=new HashSet();//一個地址對應一種花
      public Address() {
            super();
      }
      public Address(String nation, String postcode) {
            super();
            this.nation = nation;
            this.postcode = postcode;
      }
     
      public Set getFruits() {
            return fruits;
      }
      public void setFruits(Set fruits) {
            this.fruits = fruits;
      }
      public Integer getAid() {
            return aid;
      }
      public void setAid(Integer aid) {
            this.aid = aid;
      }
      public void setFruit(Fruit fruit) {
            fruits.add(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類:
create table T_FRUIT_many2many(
   FID number(10) PRIMARY KEY,
   NAME VARCHAR2(20) NOT NULL,
   COMMENTS VARCHAR2(50),
   PRICE number(5) NOT NULL
);
 
Address類:
這個是多的一方,所以他的外鍵的值要引用Fruit類的主鍵值
CREATE TABLE T_ADDRESS_many2many(
   AID number(10) PRIMARY KEY,
   NATION VARCHAR2(30) NOT NULL,
   POSTCODE VARCHAR2(10) NOT NULL
);
 
中間表:
CREATE TABLE FRUIT_ADDRESS(
   FID number(10) NOT NULL REFERENCES T_FRUIT_MANY2MANY(FID),
   AID number(10) NOT NULL REFERENCES T_ADDRESS_MANY2MANY(AID),
   PRIMARY KEY(FID,AID)
);
 
映射配置文件:
<?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.Jmtn.business.entity">
      <class name="Fruit" table="T_FRUIT_many2many">
           <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>
          <set name="addresses" table="fruit_address" inverse="true" cascade="save-update">
                 <key column="fid"></key>
                 <many-to-many class="Address" column="aid"></many-to-many>
            </set>
      </class>
      <class name="Address" table="t_address_many2many">
           <id name="aid" column="aid">
                 <generator class="hilo">
                     <param name="table">t_hilo</param>
                       <param name="column">hilo_id</param>
                 </generator>
            </id>
            <property name="nation" column="nation"></property>
          <property name="postcode" column="postcode"></property>
           <set name="fruits" table="fruit_address" cascade="save-update">
                 <key column="aid"></key>
                 <many-to-many class="Fruit" column="fid"></many-to-many>
            </set>
      </class>
</hibernate-mapping>
 
cline類:
/**
 * 知識點:
 * 基數關係映射:many to many
 */
package Yuchen.Jmtn.client;
 
import Yuchen.Jmtn.business.Biz.FruitManager;
import Yuchen.Jmtn.business.entity.Address;
import Yuchen.Jmtn.business.entity.Fruit;
 
public class Test {
     
      public static void main(String[] args){
            FruitManager fm=new FruitManager();
            Address address1=new Address("北京","0000");
            Address address2=new Address("上海","000340");
           Fruit fruit=new Fruit("玫瑰","紅色",2000);
           Fruit fruit2=new Fruit("紫羅蘭","紫色",1000);
            fruit.setAddress(address1);
            fruit.setAddress(address2);
            fruit2.setAddress(address1);
            fm.insert(fruit);
            fm.insert(fruit2);
      }
}
 
繼承關係的映射:三個表
發現問題:如何體現繼承關係呢?
兩種方式:1.共享主鍵 2.外鍵唯一
繼承中子類有一個supper,也就是有一個父類,但是父類中沒有子類,所以是單向的一對一的關係,因此在繼承中不考慮數量的問題
優點:和麪向對象的概念相似,支持多態
缺點:子類的數據會存放很多,效率也不高,表也多,但是數據沒有冗餘
 
引例:Extends包
1.     建立工具包類(省略)
2.     建立實體類
付款方式: 現金 銀行
package Yuchen.Extends.business.entity;
//父類:付款方式
public abstract class Payment {
      private Integer pid;
      private String reason;//付款原因
      private Double amount;//付款金額
     
      public Payment() {
            super();
      }
 
      public Payment(String reason, Double amount) {
            super();
            this.reason = reason;
            this.amount = amount;
      }
 
      public Double getAmount() {
            return amount;
      }
 
      public void setAmount(Double amount) {
            this.amount = amount;
      }
 
      public Integer getPid() {
            return pid;
      }
 
      public void setPid(Integer pid) {
            this.pid = pid;
      }
 
      public String getReason() {
            return reason;
      }
 
      public void setReason(String reason) {
            this.reason = reason;
      }
     
}
 
package Yuchen.Extends.business.entity;
//銀行付款
public class CardPayment extends Payment{
      private Integer pid;
      private String bank;//銀行卡
 
     
      public CardPayment() {
            super();
      }
     
 
      public CardPayment(String reason, Double omount, String bank) {
            super(reason,omount);
            this.bank = bank;
      }
 
 
      public Integer getPid() {
            return pid;
      }
 
 
      public void setPid(Integer pid) {
            this.pid = pid;
      }
 
 
      public String getBank() {
            return bank;
      }
 
      public void setBank(String bank) {
            this.bank = bank;
      }
     
     
}
 
package Yuchen.Extends.business.entity;
//現金
public class CashPayment extends Payment{
      private Integer pid;
      private String cash;//貨幣類型
      public CashPayment(){
          
      }
      public CashPayment(String reason,double amount, String cash) {
            super(reason,amount);
            this.cash = cash;
      }
      public String getCash() {
            return cash;
      }
      public void setCash(String cash) {
            this.cash = cash;
      }
      public Integer getPid() {
            return pid;
      }
      public void setPid(Integer pid) {
            this.pid = pid;
      }
     
}
 
建表:
1.Payment
create table t_payment (
      pid number(10) primary key,
      reason varchar2(30) not null,
      amount number(30) not null
);
 
2.CardPayment
//共享主鍵
create table t_cardpayment(
      pid number(10) primary key references t_payment(pid),
      bank varchar2(30) not null
);
 
3.CashPayment
//共享主鍵
create table t_cashpayment(
      pid number(10) primary key references t_payment(pid),
      cash varchar2(30) not null
);
 
寫配置文件:
<?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.Extends.business.entity">
<class name="Payment" table="t_payment">
      <id name="pid" column="pid">
            <generator class="hilo">
                 <param name="table">t_hilo</param>
                 <param name="column">hilo_id</param>
            </generator>
      </id>
      <property name="reason"></property>
      <property name="amount"></property>
      <joined-subclass name="CardPayment" table="t_cardpayment">
           <key column="pid"></key>
            <property name="bank"></property>
      </joined-subclass>
      <joined-subclass name="CashPayment" table="t_cashpayment">
           <key column="pid"></key>
            <property name="cash"></property>
      </joined-subclass>
</class>
</hibernate-mapping>
client:
/**
 * 知識點:
 * 繼承關係映射
 * test1():三個表
 */
package Yuchen.Extends.client;
 
import org.hibernate.Session;
import org.hibernate.Transaction;
 
import Yuchen.Extends.business.entity.CardPayment;
import Yuchen.Extends.util.HbnUtil;
 
public class Test {
     
      public static void test1(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            CardPayment card=new CardPayment("買雜誌",100.0,"人民幣");
            session.save(card);
            t.commit();
            session.close();
      }
      public static void main(String[] args) {
           // TODO 自動生成方法存根
            Test.test1();
      }
 
}
 
繼承關係的映射:兩個表
一個子類一個表,父類不建表,但是每個子類需要加入父類的屬性
缺點:不支持多態的查詢,特點不明顯,用的很少
 
建表:
兩個表:
1.CardPayment
create table t_cardpayment_concrete(
    pid integer(10) primary key,
    reason varchar(30) not null,
    amount double not null,
    bank varchar(10) not null
 
);
 
 
2.CashPayment
create table t_cashpayment_concrete(
    pid integer(10) primary key,
    reason varchar(30) not null,
    amount double not null,
    cash varchar(10) not null
);
修改配置文件:
<?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.Extends.business.entity">
      <class name="Payment">
           <id name="pid" column="pid">
                 <generator class="hilo">
                       <param name="table">t_hilo</param>
                       <param name="column">hilo_id</param>
                 </generator>
         </id>
            <property name="reason"></property>
            <property name="amount"></property>
            <union-subclass name="CardPayment" table="t_cardpayment_concrete">
            <property name="bank"></property>
            </union-subclass>
            <union-subclass name="CashPayment" table="t_cashpayment_concrete">
            <property name="cash"></property>
      </union-subclass>
      </class>
</hibernate-mapping>
 
繼承關係的映射:一個表
優點:1.生成報表快 2.易於實現 3.支持多態
缺點:修改和維護比較麻煩
如果類中的屬性太多用這個方法就不大合適了
建表:
一個表:
create table t_payment_hierarchy(
 pid number(10) primary key,
 reason varchar2(30) not null,
 amount number not null,
 cash varchar2(10) not null,
 bank varchar2(10) not null,
 type varchar2(10) not null
);
 
修改配置文件:
<?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.Extends.business.entity">
<class name="Payment" table="t_payment_hierarchy">
      <id name="pid" column="pid">
                 <generator class="hilo">
                       <param name="table">t_hilo</param>
                       <param name="column">hilo_id</param>
                 </generator>
   </id>
      <discriminator column="type"></discriminator>
      <property name="reason"></property>
      <property name="amount"></property>
      <subclass name="CardPayment" discriminator-value="card">
            <property name="bank"></property>
      </subclass>
      <subclass name="CashPayment" discriminator-value="cash">
            <property name="cash"></property>
      </subclass>
</class>
</hibernate-mapping>
 
組件映射 and Query:
什麼是組件映射?
我們知道在類的關聯關係中有一種關係叫組合關係,什麼是組合關係呢?就是不能獨立存在的類,我們以前在映射這種關係的時候在一對一的情況下使用的是one to one的映射方法,這種方法比較複雜,那麼我們可以使用組件映射的方法使得映射更簡單
語法:
1.     被包含的對象沒有oid,組件類不能看做po
2.     組件類不映射一個表
作用:只有一個表,沒有1to1的關係, 使得映射更簡單
引例:
銀行帳戶,有兩個類,一個是帳戶基本信息類,另一個是帳戶人詳細地址類
建立實體類:
地址類屬於值對象,帳戶類屬於實體對象,兩者之間是組合關係
package Yuchen.component.business.entity;
//帳號信息類
public class Account{
      private Integer aid;
      private String name;
      private Address address;//地址
      public Account() {
            super();
      }
      public Account(String name, Address address) {
            super();
            this.name = name;
            this.address = address;
      }
      public Address getAddress() {
            return address;
      }
      public void setAddress(Address address) {
            this.address = address;
      }
      public Integer getAid() {
            return aid;
      }
      public void setAid(Integer aid) {
            this.aid = aid;
      }
      public String getName() {
            return name;
      }
      public void setName(String name) {
            this.name = name;
      }
     
}
 
package Yuchen.component.business.entity;
//詳細地址類:注意不需要id,因爲要和Account建一個表裏
public class Address{
      private String street;//街道
      private String city;//城市
      private String zipcode;//郵編
      public Address() {
            super();
      }
      public Address(String street, String city, String zipcode) {
            super();
            this.street = street;
            this.city = city;
            this.zipcode = zipcode;
      }
      public String getCity() {
            return city;
      }
      public void setCity(String city) {
            this.city = city;
      }
      public String getStreet() {
            return street;
      }
      public void setStreet(String street) {
            this.street = street;
      }
      public String getZipcode() {
            return zipcode;
      }
      public void setZipcode(String zipcode) {
            this.zipcode = zipcode;
      }
     
}
 
建表:
create table t_component(
      aid number(10) primary key,
      name varchar2(30) not null,
      street varchar(30) not null,
      city varchar(30) not null,
      zipcode varchar(30) not null
);
 
映射文件:
<?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.component.business.entity">
      <class name="Account" table="t_component">
           <id name="aid" column="aid">
                 <generator class="hilo">
                       <param name="table">t_hilo</param>
                       <param name="column">hilo_id</param>
                 </generator>
            </id>
            <property name="name" />
            <component name="address">
                 <property name="street" />
                 <property name="city" />
                 <property name="zipcode" />
            </component>
      </class>
</hibernate-mapping>
 
client:
/**
 * 知識點:
 * 組件映射
 */
package Yuchen.component.client;
 
import org.hibernate.Session;
import org.hibernate.Transaction;
 
import Yuchen.component.business.entity.Account;
import Yuchen.component.business.entity.Address;
import Yuchen.component.util.HbnUtil;
 
public class Test{
      public static void test(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            Address address=new Address("湖南路","上海","010000");
            Account account=new Account("lisi",address);
            session.save(account);
            t.commit();
            session.close();
      }
      public static void main(String[] args){
            Test.test();
      }
}
 
Query:
/**
 * 知識點:
 * 組件映射,Query查詢
 * test1():組件映射
 * test2():1.條件查詢 2.from Object 3.uniqueResult()
 * test3():複雜的條件查詢(支持like等)
 * test4():加參數的查詢
 * test5():使用select:1.查詢一個類中引用類型的屬性值
 *                               2.查詢一個類中引用類型的對象
 * test6(): 查看兩個對象的屬性(對象數組太麻煩)
 * test7(): 使用中間對象查看兩個對象的屬性
 *            1.建一箇中間對象類
 *            2.寫select HQL語句調用API
 * test8():命名查詢
 *            1.修改配置文件
 *            2.執行API
 * API:
 * uniqueResult():返回唯一的對象
 * getNameQuery():得到變量名所指定的sql語句
 */
package Yuchen.component.client;
 
import java.util.Iterator;
import java.util.List;
 
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
 
import Yuchen.component.business.entity.Account;
import Yuchen.component.business.entity.AccountAddress;
import Yuchen.component.business.entity.Address;
import Yuchen.component.util.HbnUtil;
 
public class Test{
      public static void test(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            Address address=new Address("湖南路","上海","010000");
            Account account=new Account("lisi",address);
            session.save(account);
            t.commit();
            session.close();
      }
      public static void test2()
      {
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
//       Query q=session.createQuery("from Account where name='lisi'");
            Query q=session.createQuery("from java.lang.Object");
           List list=q.list();
            Account account=(Account) list.get(1);
//       Account account=(Account) q.uniqueResult();
            System.out.println(account.getName());
            t.commit();
            session.close();
      }
     
      public static void test3(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            Query q=session.createQuery("from Account a where a.name like '%si'");
            Account account=(Account) q.uniqueResult();
            System.out.println(account.getName());
            t.commit();
            session.close();
      }
      public static void test4(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            Query q=session.createQuery("from Account a where a.name like :x");
            q.setString("x", "%si");
            Account account=(Account) q.uniqueResult();
            System.out.println(account.getName());
            t.commit();
            session.close();
      }
     
      public static void test5(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
//       Query q=session.createQuery("select a.address.city from Account a where a.name='lisi'");
            Query q=session.createQuery("select a.address from Account a where a.name='lisi'");
            Address address=(Address) q.uniqueResult();
            System.out.println(address.getCity());
//       String city=(String) q.uniqueResult();
//       System.out.println(city);
            t.commit();
            session.close();
      }
     
      public static void test6(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            Query q=session.createQuery("select a.name,a.address from Account a");
           List list=q.list();
            Object[] obj=(Object[]) list.get(0);//第一條(name,address組成的對象數組)
//       Object[] obj2=(Object[]) list.get(1);//第二條
            System.out.println(obj[0]);
            System.out.println(((Address)obj[1]).getCity());
            t.commit();
            session.close();
      }
      public static void test7(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            Query q=session.createQuery("select new Yuchen.component.business.entity.AccountAddress(a.name,a.address.zipcode) from Account a");
           List list=q.list();
            Iterator it=list.iterator();
            while(it.hasNext()){
                 AccountAddress aa=(AccountAddress) it.next();
                 System.out.println(aa.getName());
                 System.out.println(aa.getZipcode());
           }
            t.commit();
            session.close();
      }
      public static void test8(){
            Session session=HbnUtil.getSession();
            Transaction t=session.beginTransaction();
            Query query=session.getNamedQuery("mingming");
            query.setString("name","%si");
            Account aa=(Account) query.uniqueResult();
            System.out.println(aa.getName());
            t.commit();
            session.close();
      }
      public static void main(String[] args){
            Test.test8();
      }
}
 
修改配置文件:
在class後加入:
<query name="mingming"><![CDATA[from Account a where a.name like :name]]></query>
 


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yuchen2008/archive/2007/02/17/1511291.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章