如果您已經(jīng)看完了三個準(zhǔn)備,所以看此文章是沒有問題的,如果沒有看完請點(diǎn)擊此處回到上一篇。
下面我們正式開始我們的七個步驟
步驟1: 裝配hibernate.cfg.xml
這里我們還是使用上一個筆記的代碼繼續(xù)往下寫,這里我們創(chuàng)建一個測試類HibernateTest
,在此類中有一個hibernateTest1()
方法,我這里使用單元測試,所以不需要main()
大家也可以使用main方法來調(diào)用都是也可以。
//第一步 裝載hibernate.cfg.xml
//Configuration() 可是使用有參數(shù)構(gòu)造,可以填寫你指定的hibernate的文件名,例如hiber.cfg.xml
//如果不填寫則默認(rèn)裝載src根目錄下的hibernate.cfg.xml
Configuration configuration = new Configuration();
步驟2: 創(chuàng)建SessionFactory
Hibernate 3.x版本創(chuàng)建SessionFactory方法
//Hibernate 3.x版本創(chuàng)建SessionFactory方法
SessionFactory sessionFactory = configuration.buildSessionFactory();
Hibernate 4.x版本以上創(chuàng)建SessionFactory方法
//Hibernate 4.x版本創(chuàng)建SessionFactory方法
//ServiceRegistry接口:任何配置和服務(wù)都需要在該對象注冊后才能有效
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
用4.x版本創(chuàng)建SessionFactory的時候要注意如果沒有找到new ServiceRegistryBuilder()
對象要使用一下方式創(chuàng)建SessionFactory
ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
SessionFactory sf = configuration.buildSessionFactory(sr);
Hibernate 5.x版本以上創(chuàng)建SessionFactory方法,我只想說呵呵,這個更變態(tài)
//Hibernate 5.x版本創(chuàng)建SessionFactory方法
//StandardServiceRegistry接口是一個標(biāo)準(zhǔn)服務(wù)注冊接口,擴(kuò)展ServiceRegistry
//使用StandardServiceRegistryBuilder()生成標(biāo)準(zhǔn)ServiceRegistry實(shí)例。
//configure() 此方法是來加載hibernate.cfg.xml文件,也就是說使用Hibernate5.x,我們可以省略第一步
//build() 此方法是用來構(gòu)建StandardServiceRegistry
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
//我們在上面只是創(chuàng)建了一個標(biāo)準(zhǔn)的服務(wù),但是Hibernate并不知道我們的映射有那些所以需要創(chuàng)建Metadata對象
//Metadata對象表示從映射來源確定orm模型,然后在通過buildSessionFactory()方法來創(chuàng)建SessionFactory對象
SessionFactory sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
步驟3: 創(chuàng)建Session
Session session = sessionFactory.openSession();
步驟4: 開啟事務(wù)
Transaction transaction = session.getTransaction();
//事務(wù)就不需要多說了吧,oracle的增刪改都離不開事務(wù)。
步驟5: 執(zhí)行添加
//我們先創(chuàng)建一個User對象
User user = new User();
user.setId(1);
user.setName("張三");
user.setPwd("123");
//然后執(zhí)行Hibernate的保存操作
session.save(user);
步驟6: 提交事務(wù)
transaction.commit();
//提交事務(wù),做數(shù)據(jù)持久化操作
步驟7: 關(guān)閉Seession
session.close();
這里要注意 為什么不一起關(guān)閉SessionFactory呢?
因?yàn)镾essionFactory是Session的工廠,整個程序創(chuàng)建一次就可以,我們要到Session的時候直接從工廠獲取,也就是sessionFactory.openSession()
這個方法;而程序結(jié)束會自動釋放SessionFactory對象所以不需要我們關(guān)閉,當(dāng)然在此例程序中你也可以手動關(guān)閉。
運(yùn)行程序,做測試
到此為止,我們的三個準(zhǔn)備和七個步驟已經(jīng)做完了;現(xiàn)在我們可以運(yùn)行一下我們的程序
好的非常漂亮,一個小小的程序都給我報錯了,好的上面說類為找到異常,而且提示出那個類沒有找到,可以看到并不是我們自己寫的類,還有繼續(xù)往下看提示我們發(fā)現(xiàn)是因?yàn)槲覀兊膯卧獪y試引起的,所以我們需要找到對應(yīng)的架包,添加上去即可。
好吧再一次出錯了
org.hibernate.MappingException: Repeated column in mapping for entity: cc.ibadboy.hibernate.hibernate2.entity.User column: name (should be mapped with insert="false" update="false")
他說我的映射異常,而且已經(jīng)告訴我們是那個實(shí)體類了cc.ibadboy.hibernate.hibernate2.entity.User
,并且提示我們 column: name
, 那么我們就找這個實(shí)體類的映射文件,發(fā)現(xiàn)
<property name="name" type="java.lang.String" column="name" length="50" not-null="true"/>
<property name="pwd" type="java.lang.String" column="name" length="50" not-null="true"/>
發(fā)現(xiàn)column數(shù)據(jù)值相同,我們應(yīng)該將name="pwd"
的column屬性值改為pwd
<property name="name" type="java.lang.String" column="name" length="50" not-null="true"/>
<property name="pwd" type="java.lang.String" column="pwd" length="50" not-null="true"/>
我們繼續(xù)調(diào)試程序,又出錯了 但是這個錯誤非常好
可以看到 我們的程序沒有用到JNDI為什么會出現(xiàn)這個錯誤呢?而且為什么提示我說
Error parsing JNDI name [foo]
這是因?yàn)槲覀兊?code>hibernate.cfg.xml配置文件中的<session-factory/>
標(biāo)簽有一個name屬性,這個name屬性值為foo,當(dāng)我們設(shè)置此屬性Hibernate試圖將這個sessionFacoty注冊到JNDI中,我們項(xiàng)目沒有用到JNDI所以會出錯的。記下來看第二個問題org.hibernate.TransactionException: Transaction not successfully started
事務(wù)沒有成功開啟,但是我前面已經(jīng)使用session.getTransaction();獲取到了事務(wù)了啊,為什么失敗呢?是的
session.getTransaction();
的確會獲取事務(wù),獲取的是session對象所開啟的事務(wù),你的session對象都沒有開啟事務(wù)所以當(dāng)然獲取不到啊。
而這里我們要使用
session.beginTransaction();
來開啟事務(wù),這里希望大家注意一下,你雖然使用sessionFactory.openSession();
來獲取了一個Session對象,但獲取的僅僅只是一個Session對象而已,并沒有自動的為我們開啟事務(wù)。
好的兩個錯誤解決完了,我們繼續(xù)調(diào)試吧
好了調(diào)試成功可以看到輸出的sql語句,1.先刪除了表。2.為我們創(chuàng)建了新表。3.插入了我們的數(shù)據(jù)。
這里未必非要使用oracle數(shù)據(jù)庫你用mysql也是可以的,前面我們也說了hibernate會為我們自動生成sql語句,生成的sql語句肯定也是對應(yīng)你使用的數(shù)據(jù)庫的啊。
注意
細(xì)心的讀者可能會意識到,為什么我們通過main()
方法或者單元測試,也可以通過hibernate來做數(shù)據(jù)持久化,而不需要通過web容器(如:tomcat)呢?
答:因?yàn)閐ao、serivce層根web容器沒有關(guān)系。
詳細(xì)說說用到的接口和類的作用
在上面的代碼中我們要到了一些接口和類,雖然在代碼注釋中有寫到,但是我在這里在做一下總結(jié).
????1.Configuration:通過加載配置文件管理獲取并管理配置信息,默認(rèn)讀取hibernate.cfg.xml文件;如果你需要自定義配置文件(*.cfg.xml)那么就需要使用new Configuration().configuration(*.cfg.xml)
,星號表示你自己的文件名,當(dāng)然也可以傳入一個File對象。
????2.SessionFactory:是Session工廠類,專門幫我們來new Session的;SessionFactory也有一個緩存機(jī)制,稱為二級緩存可以作用在進(jìn)程或集群上。也可以說hibernate的二級緩存是SessionFactory維護(hù)的。在大多數(shù)情況下SessionFactory在整個應(yīng)用程序中只創(chuàng)建一次。
????3.Session:是我們以后用的主要對象。此對象是比較輕量級的,我們以后可以隨便創(chuàng)建;而我們的增刪改查操作,都是通過此對象來完成。注意:一個Session對象只可以由一個線程使用。我們可以想想一下,當(dāng)一個瀏覽器發(fā)送請求到tomcat服務(wù)器的時候,tomcat會開啟一個線程操作,這個線程里面調(diào)用我們的action->serivce->dao,而在dao中有我們的hibernate的一些操作,所以會啟動(通過SessionFactory獲取)一個Session對象。每一次瀏覽器發(fā)送請求到tomcat服務(wù)器的時候都會執(zhí)行以上操作,所以說Session對象是屬于我們一個線程中的,也可以說成Session對象由一個線程使用。
????4.Transaction:用來管理事務(wù)的。我們需要在增刪改的時候需要開啟事務(wù)。注意:hibernate中的事務(wù)是不會自動提交的。
????5.StandardServiceRegistry:一個標(biāo)準(zhǔn)服務(wù)注冊接口,擴(kuò)展ServiceRegistry使用StandardServiceRegistryBuilder()生成標(biāo)準(zhǔn)ServiceRegistry實(shí)例。
????6.Metadata:從映射來源確定orm模型,然后在通過buildSessionFactory()方法來創(chuàng)建SessionFactory對象。
我個人感覺這些代碼不許要特意記住,用到的時候拷貝就可以了,而且最后會通過Spring整合,整合后更用不上了。
大大的總結(jié)
????1.Configuration:加載hibernate.cfg.xml文件。讀取用戶名、密碼、方言、映射信息等。而讀取的數(shù)據(jù)信息,全部放在SessionFactory對象中的。
????2.SessionFactory:根據(jù)單個數(shù)據(jù)(單個hibernate.cfg.xml文件)編譯后的內(nèi)存鏡像,編譯無法改變,都是從這里來獲取Session對象。我個人認(rèn)為SessionFactory有點(diǎn)像你使用jdbc來操作數(shù)據(jù)庫時的Connection對象。
????3.Session:封裝了JDBC的操作,通過Session中的方法,可以簡化復(fù)雜的JDBC操作。我個人因?yàn)镾ession有點(diǎn)像你使用jdbc來操作數(shù)據(jù)庫時的PreparedStatement對象。
資源下載
本節(jié)筆記代碼我已經(jīng)上傳到了github上大家可以點(diǎn)擊下載
下載鏈接:Hibernate3.zip