作為SSH三大框架之一的Hibernate,是用來把程序的Dao層和數據庫打交道用的,它封裝了JDBC的步驟,是我們對數據庫的操作更加簡單,更加快捷。利用Hibernate框架我們就可以不再編寫重復的JDBC代碼,不再反復的測試我們的SQL語句寫的如何。這裡這需要我們簡單配置,調用框架給我們提供的方法,就可以完成對數據增刪改查的,那麼Hibernate到底是個什麼樣的框架呢?如何使用呢?先看一個關於Hibernate框架的知識體系圖:
Hibernate有什麼好處?
:一、Hibernate是JDBC的輕量級的對象封裝,它是一個獨立的對象持久層框架,和App Server,和EJB沒有什麼必然的聯系。Hibernate可以用在任何JDBC可以使用的場合,例如Java應用程序的數據庫訪問代碼,DAO接口的實現類,甚至可以是BMP裡面的訪問數據庫的代碼。從這個意義上來說,Hibernate和EB不是一個范疇的東西,也不存在非此即彼的關系。
二、Hibernate是一個和JDBC密切關聯的框架,所以Hibernate的兼容性和JDBC驅動,和數據庫都有一定的關系,但是和使用它的Java程序,和App Server沒有任何關系,也不存在兼容性問題。
三、Hibernate不能用來直接和Entity Bean做對比,只有放在整個J2EE項目的框架中才能比較。並且即使是放在軟件整體框架中來看,Hibernate也是做為JDBC的替代者出現的,而不是Entity Bean的替代者出現的,讓我再列一次我已經列n次的框架結構:
傳統的架構:
1) Session Bean <-> Entity Bean <-> DB
為了解決性能障礙的替代架構:
2) Session Bean <-> DAO <-> JDBC <-> DB
使用Hibernate來提高上面架構的開發效率的架構:
3) Session Bean <-> DAO <-> Hibernate <-> DB
就上面3個架構來分析:
1、內存消耗:采用JDBC的架構2無疑是最省內存的,Hibernate的架構3次之,EB的架構1最差。
2、運行效率:如果JDBC的代碼寫的非常優化,那麼JDBC架構運行效率最高,但是實際項目中,這一點幾乎做不到,這需要程序員非常精通JDBC,運用Batch語句,調整PreapredStatement的Batch Size和Fetch Size等參數,以及在必要的情況下采用結果集cache等等。而一般情況下程序員是做不到這一點的。因此Hibernate架構表現出最快的運行效率。EB的架構效率會差的很遠。
3、開發效率:在有JBuilder的支持下以及簡單的項目,EB架構開發效率最高,JDBC次之,Hibernate最差。但是在大的項目,特別是持久層關系映射很復雜的情況下,Hibernate效率高的驚人,JDBC次之,而EB架構很可能會失敗。
4、分布式,安全檢查,集群,負載均衡的支持
由於有SB做為Facade,3個架構沒有區別。
四、EB和Hibernate學習難度在哪裡?
EB的難度在哪裡?不在復雜的XML配置文件上,而在於EB運用稍微不慎,就有嚴重的性能障礙。所以難在你需要學習很多EJB設計模式來避開性能問題,需要學習App Server和EB的配置來優化EB的運行效率。做EB的開發工作,程序員的大部分精力都被放到了EB的性能問題上了,反而沒有更多的精力關注本身就主要投入精力去考慮的對象持久層的設計上來。
Hibernate難在哪裡?不在Hibernate本身的復雜,實際上Hibernate非常的簡單,難在Hibernate太靈活了。
當你用EB來實現持久層的時候,你會發現EB實在是太笨拙了,笨拙到你根本沒有什麼可以選擇的余地,所以你根本就不用花費精力去設計方案,去平衡方案的好壞,去費腦筋考慮選擇哪個方案,因為只有唯一的方案擺在你面前,你只能這麼做,沒得選擇。
Hibernate相反,它太靈活了,相同的問題,你至少可以設計出十幾種方案來解決,所以特別的犯難,究竟用這個,還是用那個呢?這些方案之間到底有什麼區別呢?他們的運行原理有什麼不同?運行效率哪個比較好?光是主鍵生成,就有七八種方案供你選擇,你為難不為難?集合屬性可以用Set,可以用List,還可以用Bag,到底哪個效率高,你為難不為難?查詢可以用iterator,可以用list,哪個好,有什麼區別?你為難不為難?復合主鍵你可以直接在hbm裡面配置,也可以自定義CustomerType,哪種比較好些?你為難不為難?對於一個表,你可以選擇單一映射一個對象,也可以映射成父子對象,還可以映射成兩個1:1的對象,在什麼情況下用哪種方案比較好,你為難不為難?
這個列表可以一直開列下去,直到你不想再看下去為止。當你面前擺著無數的眼花缭亂的方案的時候,你會覺得幸福呢?還是悲哀呢?如果你是一個負責的程序員,那麼你一定會仔細研究每種方案的區別,每種方案的效率,每種方案的適用場合,你會覺得你已經陷入進去拔不出來了。如果是用EB,你第一秒種就已經做出了決定,根本沒得選擇,比如說集合屬性,你只能用Collection,如果是Hibernate,你會在Bag,List和Set之間來回猶豫不決,甚至搞不清楚的話,程序都沒有辦法寫。
Hibernate的核心組件
在基於MVC設計模式的JAVA WEB應用中,Hibernate可以作為模型層/數據訪問層。它通過配置文件(hibernate.properties或hibernate.cfg.xml)和映射文件(***.hbm.xml)把JAVA對象或PO(Persistent Object,持久化對象)映射到數據庫中的數據庫,然後通過操作PO,對數據表中的數據進行增,刪,改,查等操作。
除配置文件,映射文件和持久化類外,Hibernate的核心組件包括以下幾部分:
a)Configuration類:用來讀取Hibernate配置文件,並生成SessionFactory對象。
b)SessionFactory接口:產生Session實例工廠。
c)Session接口:用來操作PO。它有get(),load(),save(),update()和delete()等方法用來對PO進行加載,保存,更新及刪除等操作。它是Hibernate的核心接口。
d)Query接口:用來對PO進行查詢操。它可以從Session的createQuery()方法生成。
e)Transaction接口:用來管理Hibernate事務,它主要方法有commit()和rollback(),可以從Session的beginTrancation()方法生成。
Persistent Object
持久化對象可以是普通的Javabeans,惟一特殊的是它們與(僅一個)Session相關聯。JavaBeans在Hibernate中存在三種狀態:
1.臨時狀態(transient):當一個JavaBean對象在內存中孤立存在,不與數據庫中的數據有任何關聯關系時,那麼這個JavaBeans對象就稱為臨時對象(Transient Object)。
2.持久化狀態(persistent):當一個JavaBean對象與一個Session相關聯時,就變成持久化對象(Persistent Object)
3.脫管狀態(detached):在這個Session被關閉的同時,這個對象也會脫離持久化狀態,就變成脫管狀態(Detached Object),可以被應用程序的任何層自由使用,例如可以做與表示層打交道的數據輿對象(Data Transfer Object)。
Hibernate的運行過程
Hibernate的運行過程如下:
A:應用程序先調用Configration類,該類讀取Hibernate的配置文件及映射文件中的信息,並用這些信息生成一個SessionFactpry對象。
B:然後從SessionFactory對象生成一個Session對象,並用Session對象生成Transaction對象;可通過Session對象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法對PO進行加載,保存,更新,刪除等操作;在查詢的情況下,可通過Session對象生成一個Query對象,然後利用Query對象執行查詢操作;如果沒有異常,Transaction對象將 提交這些操作結果到數據庫中。
Hibernate到底是什麼?
Hibernate是一個基於元數據的輕量級的ORM框架:
1,元數據(Meta Data):data about data(數據的數據),也就是說描述一個對象數據,相當於這個對象的上下文環境。
2,輕量級:占用資源少,沒有侵入性。(其實我認為這只是相對而言,如果和Ibatis相比,它到成重量級的了)。
3,ORM:(Object Relation Mapping)對象關系數據庫的映射
這是Hibernate框架的重點,也就是說將我們程序中的實體(bean,這裡也叫POJO)和數據庫中的表進行映射。java類型和sql類型映射,面向對象設計和關系型數據庫設計的映射,從而我們只需要將更多的精力放到業務中,而不是sql數據庫方面。
4,POJO:(Plain Ordinary Java Object),無格式的普通java對象,也就是上邊說的實體,和數據庫做映射的簡單類。只是在這裡提出了一個新的名詞而已。
總而言之,Hibernate就是將我們的數據庫表和程序的POJO類進行映射,數據的操作進行了封裝,使我們不用把數據庫弄得非常精通,我們會面向對象編程就可以了,這樣大大提高了我們的編程效率,而且對個人的知識要求也降低了。(Hibernate的設計目的是這樣的,可是我覺的要想更好的應用Hibernate,更好的掌握開發的來龍去脈,這是要求我們要有更高的能力了,知其然知其所以然了)
二,環境搭建:
1,和前邊幾個框架的大概流程一樣,首先需要我們拷入必備的jar包。jar包的拷入奔著一個夠用即可的原則,用什麼拷貝什麼,當然有些日志輸出,單元測試是為了更好的觀察框架而拷入的不是必備的。這裡講到是用MySql來進行演示,所以使用了mysql的驅動jar包:
antlr-2.7.6.jar (生成SQL語句)
asm.jar(字節碼增強工具類)
c3p0-0.9.1.jar(數據源連接池組件)
cglib-2.1.3.jar(代理組件,基於繼承的)
commons-collections-2.1.1.jar(集合工具類組件,會進行高效的操作)
commons-logging-1.0.4.jar(日志輸出的轉換組件)
log4j-1.2.11.jar(日志輸出組件,更加詳細和可以控制輸出格式,及目的地)
dom4j-1.6.1.jar(XML解析)
ehcache-1.2.3.jar(緩存組件)
ejb3-persistence.jar(持久化操作的規范jar包)
hibernate3.jar(框架的核心jar包)
jta.jar(全局的事務管理)
junit-3.8.1.jar (單元測試)
mysql-connector-java-3.1.13-bin.jar (MySQL數據庫驅動jar包)
2,引入配置文件:
hibernate.cfg.xml Hibernate核心配置文件(包括數據庫的連接配置,映射文件的讀取等)
log4j.properties Log4j的日志輸出控制文件
User.hbm.xml 映射文件(這裡的User只是匹配User實體的,一個實體類對應一個此類的映射文件。)
Hibernate包目錄結構
我用的Hibernate版本是3.6.10 ,引入的庫有如下11個
Hibernate的運行過程如下圖:
核心配置文件:Hibernate.cfg.xml的編寫代碼如下
1 <!-- 我分別來寫MySQL 與 Oracle 的 下面,先寫MySQL的--> 2 <hibernate-configuration> 3 <!-- 構造數據庫的連接工廠,這是Hibernate的核心類 --> 4 <session-factory> 5 6 <!-- 這裡是簡單的數據庫連接的基本信息,也可以寫在配置文件中,或者利用JNDI來調用數據源 --> 7 <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/example?useUnicode=true&characterEncoding=utf8</property> 8 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 9 <property name="hibernate.connection.username">sm</property> 10 <property name="hibernate.connection.password">1</property> 11 12 <!-- 在控制台裡打印生成的SQL語句 --> 13 <property name="hibernate.show_sql">true</property> 14 <!-- 格式化控制台輸出的SQL語句,這兩條都是方便我們來學習Hibernate框架 --> 15 <property name="hibernate.format_sql">true</property> 16 17 18 <!-- 19 方言:根據指定的方言與數據庫打交道,完成SQL的具有語句生成,因為不同的數據庫sql語法還是有區別的, 20 這裡相當於告訴Hibernate框架,我們使用的是什麼數據庫。 21 MySQL : org.hibernate.dialect.MySQLDialect 22 Oracle : org.hibernate.dialect.OracleDialect 23 --> 24 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 25 26 <!-- 管理所有的映射資源文件,這裡僅僅配置了User類的配置映射文件,應該將我們的所有的映射配置文件設置到這裡,這樣我們框架才能找到 --> 27 <mapping resource="com/ljh/hibernate/pojo/User.hbm.xml"/> 28 29 </session-factory> 30 </hibernate-configuration> 31 32 33 34 <!--然後下面這是Orcale的--> 35 <?xml version='1.0' encoding='utf-8'?> 36 <!DOCTYPE hibernate-configuration PUBLIC 37 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 38 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 39 40 <hibernate-configuration> 41 42 <session-factory> 43 44 <!-- Database connection settings --> 45 <property name="connection.driver_class">oracle.jdbc.OracleDriver</property> 46 <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property> 47 <property name="connection.username">sm</property> 48 <property name="connection.password">1</property> 49 50 <!-- JDBC connection pool (use the built-in) --> 51 <!-- <property name="connection.pool_size">1</property> --> 52 53 <!-- SQL dialect --> 54 <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> 55 56 <!-- Echo all executed SQL to stdout --> 57 <property name="show_sql">true</property> 58 59 <!-- Drop and re-create the database schema on startup --> 60 <property name="format_sql">true</property> 61 62 <mapping class="cn.sm.entity.Student" /> 63 64 65 </session-factory> 66 67 </hibernate-configuration>
然後准備Student實體類
1 package cn.sm.entity; 2 //學生實體類 3 public class Student { 4 5 private int stuno; 6 7 private String stuname; 8 9 private int stuage; 10 11 private int stuid; 12 13 private int stuseat; 14 15 public Student() { 16 super(); 17 } 18 19 public Student(String stuname, int stuage, int stuid, int stuseat) { 20 super(); 21 this.stuname = stuname; 22 this.stuage = stuage; 23 this.stuid = stuid; 24 this.stuseat = stuseat; 25 } 26 27 public Student(int stuno, String stuname, int stuage, int stuid, int stuseat) { 28 super(); 29 this.stuno = stuno; 30 this.stuname = stuname; 31 this.stuage = stuage; 32 this.stuid = stuid; 33 this.stuseat = stuseat; 34 } 35 36 37 public int getStuid() { 38 return stuid; 39 } 40 41 public void setStuid(int stuid) { 42 this.stuid = stuid; 43 } 44 45 46 47 public int getStuseat() { 48 return stuseat; 49 } 50 51 52 53 public void setStuseat(int stuseat) { 54 this.stuseat = stuseat; 55 } 56 57 58 59 public int getStuno() { 60 return stuno; 61 } 62 63 public void setStuno(int stuno) { 64 this.stuno = stuno; 65 } 66 67 public String getStuname() { 68 return stuname; 69 } 70 71 public void setStuname(String stuname) { 72 this.stuname = stuname; 73 } 74 75 public int getStuage() { 76 return stuage; 77 } 78 79 public void setStuage(int stuage) { 80 this.stuage = stuage; 81 } 82 83 84 }
在實體類下設計映射文件Student.hbm.xml(在配置文件hibernate.cfg.xml使用)
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping package="cn.zhang.entity"> 7 <class name="Student" table="stuinfo"> 8 <id name="stuno" column="stuno"> 9 <!-- 主鍵生成策略:native: 10 native:如果後台是Oracle 11 後台是MySQL,自動應用自增 --> 12 <generator class="native"/> 13 </id> 14 <property name="stuname" type="string" column="stuname"/> 15 <property name="stuage"/> 16 17 <property name="stuid" type="int" column="stuid"/> 18 <property name="stuseat"/> 19 </class> 20 21 </hibernate-mapping>
新增一名學生
1 package cn.sm.test; 2 //新增一條數據 3 import org.hibernate.SessionFactory; 4 import org.hibernate.Transaction; 5 import org.hibernate.cfg.Configuration; 6 import org.hibernate.classic.Session; 7 8 import cn.sm.entity.Student; 9 10 public class InsertTest { 11 12 public static void main(String[] args) { 13 //准備對象 14 Student student=new Student("雲雲", 12,112333,2);//Student.hbm.xml已配置編號為自增,所以這裡不用添加編號了 15 //讀取大配置文件,獲取要連接的數據庫信息 16 Configuration configuration=new Configuration().configure(); 17 //創建SessionFactory 18 SessionFactory factory = configuration.buildSessionFactory(); 19 //加工session 20 Session openSession = factory.openSession(); 21 22 Transaction beginTransaction = openSession.beginTransaction(); 23 openSession.save(student); 24 25 beginTransaction.commit(); 26 27 System.out.println("成成成成成功!"); 28 29 } 30 31 }
修改一名學生信息
1 package cn.sm.test; 2 import org.hibernate.SessionFactory; 3 import org.hibernate.Transaction; 4 import org.hibernate.cfg.Configuration; 5 import org.hibernate.classic.Session; 6 7 import cn.sm.entity.Student; 8 9 public class UpdateTest { 10 11 /** 12 * @param args 13 */ 14 public static void main(String[] args) { 15 //1.讀取大配置文件,獲取要連接的數據庫信息 16 Configuration conf=new Configuration().configure(); 17 //2.創建SessionFactory 18 SessionFactory factory =conf.buildSessionFactory(); 19 //3加工session 20 Session session = factory.openSession(); 21 Transaction tx=session.beginTransaction(); 22 //獲取對象 23 Student stu =new Student(1,"雲雲", 12,112333,2); 24 //更新 25 session.update(stu); 26 //提交事務 27 tx.commit(); 28 System.out.println("更新成成成成成功"); 29 30 31 } 32 33 }
刪除一名指定學生信息
package cn.sm.test; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.classic.Session; import cn.sm.entity.Student; public class DeleteTest { public static void main(String[] args) { //1.讀取大配置文件,獲取要連接的數據庫信息 Configuration conf=new Configuration().configure(); //2.創建SessionFactory SessionFactory factory =conf.buildSessionFactory(); //3.加工session Session session = factory.openSession(); Transaction tx=session.beginTransaction(); //獲取對象 Student stu =new Student(); stu.setStuno(3);//指定要刪除的編號 //刪除指定 session.delete(stu); //提交事務 tx.commit(); System.out.println("刪除成成成成成功"); } }
查詢一名指定學生信息
1 package cn.sm.test; 2 3 import org.hibernate.SessionFactory; 4 import org.hibernate.cfg.Configuration; 5 import org.hibernate.classic.Session; 6 7 import cn.sm.entity.Student; 8 9 public class SelectTest { 10 11 public static void main(String[] args) { 12 //1.讀取大配置文件,獲取要連接的數據庫信息 13 Configuration conf=new Configuration().configure(); 14 //2.創建SessionFactory 15 SessionFactory factory =conf.buildSessionFactory(); 16 //3.打開session 17 Session session = factory.openSession(); 18 //4.加載數據操作 19 //如果表中沒有你指定的主鍵列,get()方法的是null 20 Student student =(Student)session.get(Student.class, 4); 21 //如果表中沒有你指定的主鍵列,程序運行到student.getStuname()時會拋出異常 22 //Student student =(Student)session.load(Student.class, 4); 23 //5.輸出數據 24 System.out.println(student.getStuname()); 25 //6.關閉session 26 session.close(); 27 28 29 30 } 31 32 }
根據上面的信息,我想你應該對HIberiannate 已經有所了解了 , 敬請期待更多內容的補充! 感謝有你!