一: H ibernate的簡介
?
?
?
?
Hibernate 基本原理
1)Hibernate初始化,讀取并解析配置文件
2)讀取并解析映射信息,創建SessionFactory
3)打開SESSION
4)創建事物Transaction
5)持久化操作
6)提交事務
7)關閉Session
8)關閉SessionFactory
Hibernate的模擬實現原理
?
H
ibernate helloworld
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/b2c_v2_alpha_3c</property> <property name="connection.username">root</property> <property name="connection.password">123456</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Enable Hibernate's automatic session context management --> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!-- 寫update只是更新操作,也可以寫create, 這樣寫create的話程序運行的時候就會把數據庫里的內容全部刪除并且重新創建, 當然,前提是數據庫必須存在,因為hibernate只會創建表結構, 不會創建數據庫,如果指定的數據庫不存在,hibernate則會拋出異常 --> <property name="hbm2ddl.auto">update</property> <!-- Drop and re-create the database schema on startup --> <!-- <mapping resource="com/hibernate/model/GroupClass.hbm.xml"/> --> <mapping class="com.hibernate.model.Ith_Admin_Log"/> </session-factory> </hibernate-configuration>
?
?
package com.hibernate.model; public class GroupClass { private String class_id ; private String name; private String sort; public String getClass_id() { return class_id; } public void setClass_id(String class_id) { this.class_id = class_id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSort() { return sort; } public void setSort(String sort) { this.sort = sort; } }
?
GroupClass.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> <class name="com.hibernate.model.GroupClass" table="group_class"> <id name="class_id" column="class_id"/> <property name="name" /> <property name="sort" /> </class> </hibernate-mapping>
?
?
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import com.hibernate.model.GroupClass; public class Demo { public static void main(String []args) { GroupClass gc = new GroupClass(); gc.setClass_id(String.valueOf(System.currentTimeMillis())); gc.setName("zhudansheng"); gc.setSort("3"); //加載配置文件 Configuration config = new Configuration(); //讀取配置文件建立Session工廠 SessionFactory sf = config.configure().buildSessionFactory(); //建立連接 Session session = sf.openSession(); //開始事物 hibernate 操作數據庫都使用事物機制 session.beginTransaction(); //操作SQL session.save(gc); //獲取事物進行操作數據庫,提交 session.getTransaction().commit(); //關閉事物 session.close(); sf.close(); } }
?
?
package com.hibernate.model; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.*; //@使用注解 annotation @Entity @Table(name="admin_log") public class Ith_Admin_Log { private String log_id; private String user_id; private String log_info; private String ip; private String add_time; private String sex; private Date add_date; @Id public String getLog_id() { return log_id; } public void setLog_id(String log_id) { this.log_id = log_id; } @Column(name="add_user") public String getUser_id() { return user_id; } public void setUser_id(String user_id) { this.user_id = user_id; } public String getLog_info() { return log_info; } public void setLog_info(String log_info) { this.log_info = log_info; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getAdd_time() { return add_time; } public void setAdd_time(String add_time) { this.add_time = add_time; } //@Transient public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Temporal(TemporalType.DATE) public Date getAdd_date() { return add_date; } public void setAdd_date(Date add_date) { this.add_date = add_date; } }
?
import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import com.hibernate.model.Ith_Admin_Log; public class AnnotationnDemo { public static void main(String []args) { Ith_Admin_Log adminLog = new Ith_Admin_Log(); adminLog.setLog_id(String.valueOf(System.currentTimeMillis())); adminLog.setUser_id("2222222222222"); adminLog.setLog_info("測試建立數據庫的的連接annotation "); adminLog.setIp("222.33.22.3"); adminLog.setAdd_time("2011-2-20"); adminLog.setSex("男"); adminLog.setAdd_date(new Date()); Configuration cfg = new AnnotationConfiguration(); SessionFactory sf =cfg.configure().buildSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); session.save(adminLog); session.getTransaction().commit(); session.close(); sf.close(); } }
?
???
Hibernate目前實現由兩種方式:XML,ANNOTATION
1)XML:通過使用XML的配置關聯數據庫,操作數據庫表
2)注解(Annotation):注解使用了JPA的接口標準,其他都是JPA的實現
二:
流行ORM框架簡介
技術日新月異,今天非常流行的技術,明天或將淘汰,所以我建議學習思想,思路,原理。練習內功才是上策。
因為有了Hibernate 的支持,使得JavaEE應用的OOA (面向對象分析)、OOD(面向對象設計)和OOP(面向對象編程)三個過程一脈相承,成為一個整體.
(1)Enitiy EJB:Enitiy EJB實際上也是一種ORM技術,這是一直備受爭議的組件技術。事實上,EJB為Java EE的蓬勃發展贏得了極高的聲譽,EJB作為一種重量級、高花費的ORM技術具有不可比擬的優勢。就其他架構設計來講,依然非常優秀。即使現在十分流行的輕量級Java EE架構,其實質是對經典Java EE架構的模仿——雖然存在些許的改進。EJB3.1
也采取了低侵入式的設計,增加了Annotation,也具有極大的吸引力。
(2)Hibernate:目前最流行的開源ORM框架,已經被選作JBoss的持久層解決方案。整個HIbernate項目也一并投入了Jboss的懷抱,而JBoss又加入了RedHat組織,所以現在Hibernate屬于RedHat 的一部分。Hibernate 靈巧的設計、優秀的性能,還有其豐富的文檔都是其風靡全球的重要因素。
(3)iBatis: Apache軟件基金組織的子項目。與其稱它為一種ORM框架,不如稱它為一中“SQL Mapping”框架。曾經在J2EE的開發中扮演非常重要的角色,但因為不支持存粹的面向對象操作,因此現在逐漸地被取代。但是在一些公司,依然占有一席之地,特別是一些對數據訪問特別靈活的地方,iBatis更加的靈活,它允許開發人員直接編寫SQL語句。
(4)TopLink:Oracle公司的產品,作為一個遵循OTN協議的商業產品,TopLink 在開發過程中可以自由地下載和使用,但是一旦作為商業產品被使用,則需要收取費用。由于這一點,TopLink 的市場占有率不高。
(5)OBJ:Apache軟件基金組織的子項目。另一個開源的ORM框架,可以說是Apache作為iBatis之后的取代產品,也是非常優秀的O/R Mapping框架,但是由于Hibernate 的廣芒太盛,所以并未有廣泛的使用,而且由于OJB的開發文檔不是很多,這也影響了OJB的流行。
?
目前流行的編程語言,如Java、C#?等,它們都是面向對象的編程語言,而目前主流的數據庫產品例如Oracle、DB2等,依然是關系型數據庫。編程語言和底層數據庫發展的不協調,催生出了ORM框架。ORM框架可以作為面向對象語言和關系型數據庫之間的橋梁。
?
1. 對象/關系數據庫映射(ORM)?
??????? ORM的全稱是Object/Relation Mapping,對象/關系數據庫映射。ORM可以理解成一種規范,它概述了這類框架的基本特征:完成面向對象編程語言和關系型數據庫的映射。當ORM框架完成映射后,它既可利用面向對象程序設計語言的簡單易用性,又可以利用關系型數據庫的技術優勢。因此,我們可以把ORM框架當成是應用程序和數據庫的橋梁。
??????? 當我們使用一種面向對象程序設計語言來進行應用開發時,從項目開始起就采用的是面對對象分析、面向對象設計、面向對象編程,但到了持久層數據庫訪問時,又必須重返關系型數庫的訪問方式,這是一種糟糕的感覺。于是我們需要一種工具,它可以把關系型數據庫包裝成一個面向對象的模型,這個工具就是ORM框架。
??????? ORM是面向對象程序設計語言與關系型數據庫發展不同步時的中間解決方案。隨著面向對象數據庫的發展 ,其理論逐步完善,最終會取代關系型數據庫。只不過這個過程不會一蹴而就,ORM框架在此期間仍將蓬勃發展。但是隨著面對對象數據庫的出現,ORM工具會自動的消亡。
?????? 對時下流行的編程語言而言,面向對象程序設計語言代表了目前程序設計語言的主流和趨勢,具備了非常多的優勢。比如:
???? (1)面向對象的建模、操作
???? (2)多態、繼承
???? (3)摒棄難以理解的過程
???? (4)簡單易用易理解
?????? 但數據庫的發展并未與程序設計語言同步,而且關系數據庫的某些優勢也是面向對象的語言無法比擬的。比如:
???? (1)大量數據的查找和排序
???? (2)集合數據連接操作、映射
???? (3)數據庫訪問的并發、事務
???? (4)數據庫的約束和隔離
??????? 當我們采用ORM框架之后,應用程序不再直接訪問底層的數據庫,而是以面向對象的方式來操作持久化對象(例如創建、修改、刪除等),而ORM框架則將這些面向對象操作轉換成底層的SQL操作。
??????? 正如上圖所示ORM工具的唯一作用就是把持久化對象的操作轉換成對數據庫的操作,從此程序員可以以面向對象的方式操作持久化對象,而ORM框架則負責轉換成對應的SQL(結構化查詢語言)操作。
?
2. 基本映射方式
??????? ORM工具提供了持久化類和數據表之間的映射關系 ,通過這種關系的映射過渡,我們可以很方便地通過持久化類對數據表進行操作。實際上,所有ORM工具大致上都遵循相同的映射思路。
??????? ORM基本映射有如下這幾條映射關系:
?????? (1) 數據表映射類 :
??????? 持久化類被映射到一個數據表。當我們使用這個持久化類來創建實例、修改屬性、刪除實例時,系統自動會轉換為對這個表進行CRUD操作,下圖顯示了這種映射關系。
??????? 正如上圖所示,受ORM管理的持久化類(就是一個普通的Java類)對應一個數據表,只要我們對這個持久化類進行操作,系統可以轉換成對對應數據表的操作。
????? (2) 數據表的行映射對象(即實例):
??????? 持久化類會生成很多的實例,每個實例就對應數據表中的一行記錄。當我們在應用中修改持久化類的某個實例時,ORM工具將會轉換成對對應數據表中的特定行的操作。每個持久化對象對應數據表的一行記錄。如下圖所示:
????? (3) 數據表的列(字段)映射對象的屬性:
?????? 當我們在應用中修改某個持久化對象的制定屬性時(持久化數據映射到數據行),ORM將會轉換成對對應表中指定數據行、指定列的操作。數據表列被映射到對象屬性的示意圖如下表示:
??????? 基于這些基本的映射方式,ORM工具可完成對對象模型和關系模型之間的相互映射。由此可見, 在ORM框架中,對象持久化是一種中間媒介,應用程序只需要操作持久化對象,ORM框架則負責將這種操作轉換為底層數據庫操作——這種轉換對開發者來說透明,無需開發者關心,從而將開發者從關系模型中解放出來,使得開發者能夠以面向對象的思維操作關系型數據庫。
三:
準備階段
<!--EndFragment-->
?
?
1)hbm2ddl 的使用 update,create,delete 等等
<property?name="hbm2ddl.auto">update</property>??
?
update: 在加載 hibernate 的時候,更新數據庫的數據
create: 重新創建數據庫表結構,這樣導致的原因是數據庫表數據丟失
create-drop: 加載 hibernate 時創建,退出是刪除表結構
validate :加載 hibernate 的時候,驗證數據庫表結構
總結:請慎重使用此參數,沒必要就不要隨便用;如果發現數據庫表丟失,請檢查 hibernate.hbm2ddl.auto 的配置
?
2) 分析業務 ( 業務邏輯,業務流程 ), 再建立表 ( 建立表使用 powerdesigner), 最后建立類 (ORM 中的 O)
此處是高級程序員向產品經理或項目經理過渡的過程。
?
3) 搭建 log4j 日志查看日志信息:使用 slf4j 作為接口標準。
SLF4J ( Simple?Logging?Facade?for?Java )是一個通用的日志框架接口標準。?實現 SLF4J 的接口有很多,但是目前兼容最好的是 LOG4J 。
?
下載 SLF4J : http://www.slf4j.org/download.html
?
下載 LOG4J : http://logging.apache.org/log4j/1.2/download.html
1.?
slf4j-api-1.5.11.jar
2.?slf4j-log4j12-1.5.11.jar
3.?log4j-1.2.15.jar
4.?log4j.properties
?
?
log4j.properties?
log4j.rootLogger=DEBUG,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd?HH:mm:ss,SSS}?[%c]-[%p]?%m%n
Log4j 建議只使用四個級別,優先級從高到低分別是? ERROR 、 WARN 、 INFO 、 DEBUG
?
static?Level?DEBUG
DEBUG?Level 指出細粒度信息事件對調試應用程序是非常有幫助的。
static?Level?INFO
INFO?level 表明?消息在粗粒度級別上突出強調應用程序的運行過程。
static?Level?WARN
WARN?level 表明會出現潛在錯誤的情形。
static?Level?ERROR
ERROR?level 指出雖然發生錯誤事件,但仍然不影響系統的繼續運行。
static?Level?FATAL
FATAL?level 指出每個嚴重的錯誤事件將會導致應用程序的退出。
?
org.apache.log4j.ConsoleAppender
(控制臺)
org.apache.log4j.FileAppender
(文件)
org.apache.log4j.DailyRollingFileAppender
(每天產生一個日志文件)
org.apache.log4j.RollingFileAppender
(文件大小到達指定尺寸的時候產生一個新的文件)
org.apache.log4j.WriterAppender
(將日志信息以流格式發送到任意指定的地方)
org.apache.log4j.HTMLLayout
(
HTML
表格形式)
org.apache.log4j.SimpleLayout
(簡單格式的日志,只包括日志信息的級別和指定的信息字符串?,如
:DEBUG?-?Hello
)
org.apache.log4j.TTCCLayout
(日志的格式包括日志產生的時間、線程、類別等等信息)
org.apache.log4j.PatternLayout
(靈活地自定義日志格式)
當使用
org.apache.log4j.PatternLayout
來自定義信息格式時,可以使用
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd?HH:mm:ss}?%p?-%m%n?
來格式化信息
%c?
輸出所屬類的全名,可寫為?
%c{Num}?,Num
類名輸出的范圍?如:
"com.sun.aaa.classB",?%C{2}
將使日志輸出輸出范圍為:
aaa.classB
%d?
輸出日志時間其格式為?可指定格式?如?
%d{HH:mm:ss}
等
%l?
輸出日志事件發生位置,包括類目名、發生線程,在代碼中的行數
%n?
換行符
%m?
輸出代碼指定信息,如
info(“message”),
輸出
message
%p?
輸出日志的優先級,即?
FATAL?,ERROR?
等
%r?
輸出從啟動到顯示該條日志信息所耗費的時間(毫秒數)
%t?
輸出產生該日志事件的線程名
實例:
?
首先加入包 :
? Log4j-1.2.16.jar
? Slf4j-api-1.6.4.jar
? Slf4j-log4j12-1.6.4.jar
<!--EndFragment-->
?
Log4j.properties
?
?
#log4j.rootLogger=DEBUG,console #log4j.appender.console=org.apache.log4j.ConsoleAppender #log4j.appender.console.layout=org.apache.log4j.PatternLayout #log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd?HH:mm:ss,SSS}?[%c]-[%p]?%m%n ? log4j.rootLogger= DEBUG,LOGFILE log4j.appender.LOGFILE= org.apache.log4j.FileAppender log4j.appender.LOGFILE.file= alllog log4j.appender.LOGFILE.layout= org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern= [%-5p] ? %d{yyyy-MM-dd ? HH : mm:ss,SSS} ? |
?
?
package ?com.hibernate.slf4j; ? import ?org.slf4j.Logger; import ?org.slf4j.LoggerFactory; ? public ? class ?TestSLF4JDemo?{ public ? static ? void ?main(String?[]args)?{ Logger?logger?=LoggerFactory. getLogger (TestSLF4JDemo. class ); logger.debug( "debug?級別" ); logger.error( "ERROR?級別" ); logger.info( "INF0?級別?{}" ,?1); logger.trace( "TRACE?級別" ); logger.warn( "WARN?級別" ); } } ? |
?
4) 搭建 junit 進行測試。
JUNIT 是在程序員白盒測試的時候使用。
@BeforeClass? 加載配置文件或實例化 ,
@Test? 測試實例代碼 ,
@AfterClass? 關閉資源
?
實例:
?
導入包: junit-4.10.jar
?
package?com.hibernate.slf4j; ? import?org.slf4j.Logger; import?org.slf4j.LoggerFactory; ? public?class?TestSLF4JDemo?{ public?static?void?main(String?[]args)?{ Logger?logger?=LoggerFactory.getLogger(TestSLF4JDemo.class); logger.debug("debug? 級別 "); logger.error("ERROR? 級別 "); logger.info("INF0? 級別? {}",?1); logger.trace("TRACE? 級別 "); logger.warn("WARN? 級別 "); } ? public?static?void?test()?{ Logger?logger?=LoggerFactory.getLogger(TestSLF4JDemo.class); logger.debug("debug? 級別 "); logger.error("ERROR? 級別 "); logger.info("INF0? 級別? {}",?1); logger.trace("TRACE? 級別 "); logger.warn("WARN? 級別 "); } } |
?
?
?
package ?com.juit.test; ? import ?org.junit.AfterClass; import ?org.junit.BeforeClass; import ?org.junit.Test; ? import ?com.hibernate.slf4j.TestSLF4JDemo; ? ? public ? class ?TestDemo?{ ? @BeforeClass public ? static ? void ?BeforeClass()?{ System. out .println( "========doBeforeClassdoBeforeClassdoBef=======" ); } ? @Test public ? void ?Test()?{ System. out .println( "=======doTestdoTestdoTestdoTestdoTest========" ); ????TestSLF4JDemo. test (); } ? @AfterClass public ? static ? void ?AfterClass()?{ System. out .println( "========doAfterClassdoAfterClassdo=======" ); } } ? |
?
?
?
<!--EndFragment-->
?
?
?
?
?
?
四:Hibernate的基礎配置(重點)
?注解細講【主要是區別注解和XML】
注解:都需要位于javax.persitentice.*;可以使用@Entity
表名和類中定義的名稱不同使用@Table(name="table_name")
字段名和表中的字段名不同使用@Column(name="xxx")
不需要持久化字段:@Transient (transient)透明的
注解使用日期可以使用@Temportal(TemportalType.DATE)
hibernate annotation字段映射位置,應該放在get上面
為什么不加屬性上面。因為屬性本身就是私有的,私有的本身就不需要別人調用。
查資料的能力(獲取情報信息能力)和綜合運用能力(體現在項目)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
