|
2005年11月23日
LDAP(輕量級目錄服務器)越來越被廣泛的使用,特別是在管理海量用戶信息和管理身份認證信息的時候,LDAP被國內大多數企業所使用,從中國電信,中國移動,新浪,和許多省市政府部門都使用LDAP來管理用戶身份的信息。下面重點介紹在LDAP中管理用戶的一些概念和技巧。
LDAP服務器使用樹狀結構來存儲和查找用戶的信息。這種樹狀結構比較適合用戶身份信息的存儲,因為無論在社會還是在企業中,對人的管理是分層的。從地域上的國家、省市到區域,從企業的大部門到小部門,從總經理到小職員,所有的管理都是分層的。“人類的層次劃分是社會活動的自然產物”,忘了這句話是誰說的了,但是我們觀察自己的周圍環境,樹狀結構的分層無處不在,這也是LDAP為什么在人員管理上這么流行的原因,也是LDAP最初設計的需求。當然,在這里我們不討論人類社會活動現象,只討論LDAP技術問題。
LDAP在存儲樹狀結構的數據比關系型數據庫有很大的優勢。請試圖想想在關系數據庫中要實現這種樹狀的數據,需要費一番功夫,并且要定位層次比較深的節點的數據需要經過復雜的查詢和轉換。但是LDAP這種樹狀的結構也有一個重要的缺點,就是很難反映出除了結構層次之外的其他關系(例如在同一個組織之下的管理和被管理的關系),而且當組織結構經常發生變化的情況下,樹狀結構很難滿足這種靈活性的要求。有樹狀結構特點決定,當一個組織變化的時候,這個組織下的所有節點都需要一一變化。
因此,在LDAP中出現了Group(組)和Role(角色)來動態的管理節點之間的關系。例如,建立一個“管理員”的組或角色,然后可以將不同組織結構下的人員放到“管理員”這個邏輯結構下。那么通過“管理員”這個虛擬的組織結構可以將不同物理組織下的人員動態的組合在一起。例如給“管理員”賦予特殊的權力,使他們能夠修改本機構中的人員信息。過了一段時間,如果需要將“管理員”這個邏輯組織取消或者改動,只需要在LDAP的單個節點上操作,而實際“管理員”邏輯結構的成員們,不需要作任何的變化,原來是在哪個物理組織,現在也不用變化。這種Group(組)和Role(角色)的出現是增加了節點之間的關聯程度。
Group(組)和Role(角色)的功能基本相同,操作起來也很類似。那么Group(組)和Role(角色)到底有什么區別呢?事實上,由于實現方法不同,Group(組)和Role(角色)在某些操作上體現出不同的性能。
Group(組)的實現機制很簡單,每個Group本身就是LDAP的一個實體。這個實體有個member的屬性。每次將一個成員添加到這個Group中就會在Member屬性中添加一條記錄(成員的DN)。如果這個Group有200個成員,那么它的member屬性中會有200條記錄。這種實現方式非常適合下面的操作:1. 列舉當前Group下的所有成員。2.將一些成員從當前的Group中刪除或添加。因為所有的成員都記錄在Group實體的屬性里;這種實現方式非常不適合下面的操作:查找某個用戶所屬的所有Group。這個操作可能要去每個Group中查找信息。
Role(角色)的實現機制就比較復雜了。其實每個LDAP實體本身都有一個“nsrole”的屬性。如果某個角色賦予這個用戶的話,就會在這個用戶的“nsrole”(其實是nsroleDN,這個會在以后解釋)的屬性中添加一個角色的記錄。如果當前用戶有10個角色(例如,他又是領導,又是員工,又是管理員,又是教授....),那么在這個用戶的"nsrole"屬性中會有10條記錄(Role的DN)。這種實現方式非常適合下面的操作: 列舉當前用戶擁有的所有的角色,因為在用戶的“nsrole”屬性中記錄了所有的角色。因此給一個用戶授權通常使用角色,這是因為從用戶信息中就能很快獲得當前用戶所有的角色,以及相關的權限。
另外還有一些準則來幫助判斷在設計時到底使用Group還是Role。
1 使用Group會很容易將用戶從一系列“邏輯組織”中刪除或添加。只要是Group的創建者,就有權限修改Group中的member屬性。而角色(Role)的信息存在每個用戶的“nsroleDN”中,需要特定的權限才能修改這個屬性。
2 如果要使用分布式部署(例如使用Chaining的方式),要考慮到角色(Role)是無法跨越服務器的界限
3 如果成員數量巨大(超過20000)個,可以使用動態組的概念(FilterGroup),這個以后再將。
摘要: Lucene in Action
中文版
第一部分 Lucene核心
1. 接觸Lucene
2. 索引
3. 為程序添加搜索
4. ... 閱讀全文
UI項目的團隊組合(來自微軟的借鑒)
來源:ChinaUI
UI設計人員是對產品的使用界面進行設計和訂正的人員。 Usability Engineer是檢驗UI設計的合理性的人員。
在很多團隊,真正的界面設計都是由PM做完了Spec,才找UI設計人員來征求意見。像我們團隊,我的設計規范書寫完后,我才找UI設計人員來,他們所做的也就不過是對我的設計作小改動,如那些英語詞句用得不妥,哪里的按鈕該改變大小,等等。我所知道的其它視窗操作系統的團隊,也是差不多。這主要是因為我們能自己進行界面設計——視窗操作系統部門的PM是微軟PM中最厲害的。可是,這是不太正確的方法,因為如果你有很強的PM,你可用這種方法,要是你的 PM的設計能力不強,這樣的流程就要出問題。你的項目的成功不應該寄托在幾個強有力的PM上,而是要用完善的流程來保證。好的流程應該是,在產品開發的早期,在做設計時,PM就應該和UI設計人員一起來考慮產品設計的合理性。
這個問題在微軟內部我們自己也有很大的爭論。 UI設計人員就常常抱怨,在產品開發的早期,他們常常不被看重,被拋在一邊。UI設計的領導人甚至在全公司的培訓大會上講,我們的這個文化有問題,領導對 UI設計人員在產品開發早期能起的作用不夠重視。可是這個爭論已有幾年了,結果仍無改變。我想這主要還是跟我們這個行業的產品開發的特性有關系。因為軟件開發是很技術性的,常常在早期的技術討論中,UI設計人員對技術討論說不出個所以然來(因為他們大多是學藝術設計的),漸漸地各開發團隊對UI設計人員的作用就看輕了。在使用界面因素占很大比例的產品團隊,像 Office 和 MSN ,這種情況要好一些。
Usability Engineer 所做的事和UI設計人員不同。他們是將UI設計的模型版,找客戶來進行實用和使用性能的檢驗調查和測試,并根據調查結果對UI設計提出進行修改的意見。也就是說,他們的工作是檢驗UI設計的合理性,有點像測試人員對程序進行檢驗的功能。可以說,Usability Engineer 和UI設計人員的關系像測試人員與開發編程人員的關系。
User Education team 是編寫使用說明書的編輯人員。
從大方面的來說,微軟的產品組是公司的幾大部門之一,其他還有市場/銷售部門,服務部門,運作部門,還有研究院什么的。
合理的開發團隊組合應該是什么? 允許我拋磚引玉,先談一下微軟的經驗:
項目經理團隊:(Program Management Team) ? 設計項目經理(Feature Design PM):負責具體的產品設計,寫Design Spec,PM 隊伍中,80%的PM是做這個。 ? 發行項目經理 (Release PM):負責整個項目的流程和進度管理,制定進度表等,協調整個團隊的工作。大的PM 隊伍中有一人專門做這個。這是整個項目的領頭人。大型的項目的成功與否,常常靠得力的發行經理的領導。 ? 協助項目經理(Supporting PM):負責其它產品發行需要照顧到的事情,如客戶交流、和市場開發人員交流、負責beta program(初版試行)等等。大的PM 隊伍中少不了這樣的人。20%的PM是做這個。
開發團隊:(Development Team) ? 開發團隊領導(Development Manager): 負責管理各個開發小組,并對開發編程的工作做總體的規劃。 ? 開發組長(Development Lead): 負責管理開發工程師,也參加對開發編程的工作做總體的規劃。 ? 開發工程師(Develop Engineer,or Developer):負責具體的編程開發。 ? 構架師(Architect): 大的產品團隊有一兩個資深工程師專門做整體系統的設計規劃。
測試團隊:(Quality Assurance or Test Team) ? 測試團隊領導(QA Manager): 負責管理測試小組。 ? 測試組長(Test Lead): 負責管理測試工程師,制定測試計劃等。 ? 測試工程師(Tester or Test Engineer):負責具體的測試工作。 ? 測試開發工程師(Developer in Test,or STED): 負責測試工具的開發。
產品可用性團隊:(Usability Team) ? 產品可用性工程師(Usability Engineer): 做使用性能的調查和測試,采訪客戶或將客戶邀請來做調查。 ? 界面設計師(UI Designer): 負責具體的界面設計。 ? 產品設計師 (Product Designer): 負責產品的總體設計,特別是硬件產品。
客戶教育或文檔團隊:(User Education,or UE Team) ? 文檔組長(UE Lead):負責管理文檔小組。 ? 文檔編輯(UE Editor):負責具體的文檔編輯和撰寫。
以上只是一個大約的組合模式。不同的團隊有各自的側重點和變化。在很大程度上這些也受到具體的產品的影響。我想我在微軟的產品部門的其他同事們會再做補充。希望這些信息能對國內的軟件開發公司能有參考價值。我們希望通過這樣的交流,我們能為中國軟件開發事業的進一步發展盡我們的一點微薄之力。
WEBLOGIC是一個性能卓越的J2EE服務器,在我國的使用者在快速增長。但現在有關它的中文資料基本沒有,更沒有介紹使用經驗方面的。下面是本人在學習使用WEBLOGIC6.0中得到的一些經驗,寫出來與大家分享。 一、WEBLOGIC6.0的安裝 WEBLOGIC6.0自帶了JDK1.3,所以不用預先安裝JDK就可以直接安裝它,在WIN2000平臺是一個EXE文件,直接運行它即可;在UNIX平臺上的安裝包是一個*.bin文件,用sh運行它就可以了,最好是加 -i console的控制臺選項(如果不加,可能會報CLASSNOFOUND等錯誤)如下所示: sh weblogic60_sol.bin -i console的控制臺 注意: 1、UNIX系統的TMP目錄(環境變量TMPDIR或TMP_DIR所指的路徑)應有足夠的空間,因為WEBLOGIC6.0安裝時先解壓文件到系統的TMP目錄下,然后再進行安裝。如果TMP目錄空間不夠安裝會出錯,這時你可以把TMPDIR設到要足夠空間的目錄下。 2、如果用普通用戶安裝出錯,可試著用ROOT用戶安裝。一般是環境變量及權限的問題。 3、安裝軟件可到http://commerce.bea.com/downloads/products.jsp下載,聯機文檔可到http://edocs.bea.com/wls/docs61/index.html下載。
二、與ORACLE數據庫的連接 WEBLOGIC6.0通過ORACLE客戶端訪問ORACLE,所以在WEBLOGIC6.0所在的機器上要正確安裝ORACLE客戶端才行。WEBLOGIC6.0對ORACLE提供TYPE2的JDBC DRIVER支持,是一些動態連接庫(NT 是.DLL,UNIX是.SO)文件,在$WL_HOME\bin下,以OCI開頭的幾個目錄中。具體采用哪個目錄下庫文件,與ORACLE SERVER端及CLIENT端的版本及ORACLE API的版本有關,可參考WEBLOGIC6.0的聯機文檔。要把這些庫所在的路徑加到系統的環境變量中,否則訪問數據庫時,WEBLOGIC6.0會報以下錯誤: Java.sql.SQLException: System.loadLibrary threw java.lang.UnsatisfiedLinkError with the message 'no WEBLOGICoci37 in java.library.path'..... 在WIN2000中要加到PATH環境變量中,如: set PATH= D:\WEBLOGIC6.0\wlserver6.0\bin\oci816_7;c:\ORANT816\bin;%PATH% 在NIX平臺,要到系統的LIBRARY PATH中,如在SUN上,要加到LD_LIBRARY_PATH環境變量中,方法如下: export LD_LIBRARY_PATH=/bea/weblogic6.0/oci816_8:$ORACLE_HOME/lib 在HP平臺上,要加到SHLIB_PATH環境變量中,如: export SHLIB_PATH=/bea/ weblogic6.0/lib/hpux11/oci816_8:$ORACLE_HOME/lib
三、在WEBLOGIC6.0中設置資源的訪問權限 WEBLOGIC6.0幾乎可以對它所管理的所有資源設置訪問控制表,包括EJB、JSP、SERVLET、POOL、JMS、RMI、JNDI、JDBC等等。當用戶第一次訪問設置了訪問控制表的資源時,WEBLOGIC6.0會彈出一個對話框要求輸入口令及密碼,如果連輸3次都不對,會返回以下錯誤: Error 401--Unauthorized xxx From RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1: 10.4.2 401 Unauthorized
對訪問權限的設置有兩種方式: 1、 在WEBLOGIC6.O的控制臺中設置,把結果保存到fileRealm.properties中,即采用WEBLOGIC6.0的file realm.感覺對DATABASE POOL,EJB等比較好用,對JSP,SERVER及某個目錄設置訪問控制表比較難。我試了很多次都沒成功。它可對WEB用戶(通過瀏覽器訪問)和普通用戶(通過JAVA客戶端等訪問)起作用。 2、在WEB.XML,WEBLOGIC.XML中設置,只能對WEB用戶起作用。下面舉個例子說明這種方式。 如:在一個名為OrderWebApp的WEB APPLICATION中,客戶的定單文件都放到/orders目錄下,只有manager能瀏覽該目錄下的文件。其WEB.XML及WEBLOGIC.XML可設置如下:
*************************WEB.XML************************* <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 1.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <security-constraint>
<web-resource-collection> <web-resource-name>SecureOrdersEast</web-resource-name> <description>Security constraint for resources in the orders directory</description> <url-pattern>/orders/*</url-pattern> <http-method>POST</http-method> <http-method>GET</http-method> </web-resource-collection>
<auth-constraint> <description>constraint for orders</description> <role-name>manager</role-name> </auth-constraint>
<user-data-constraint> <description>SSL not required</description> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint>
</security-constraint>
<security-role> <description>managers</description> <role-name>manager</role-name> </security-role>
</web-app>
說明:<security-constraint>中定義資源的訪問控制表。在<web-resource-collection>中定義資源及其存取方式;在<auth-constraint>中定義可訪問該資源的角色;在 <user-data-constraint>中定義WEBLOGIC SERVER與CLIENT之間的開始通訊時,是否采用SSL建立連接。?lt;security-role>中定義角色名。
以下的幾個服務器可以免費下載或者進行開發:
Blazix (1.5 Megabytes, JSP, Servlets and EJBs) 來自www.blazix.com/blazix.html
ServletExec (3.8 Megabytes, JSP and Servlets) 來自www.unifyeware.com/servletExec/
所周知,發布一個由JSP/SERVLET開發的網站,除了需要相應的WEB服務器來響應普通網頁的請求外還需要專門的應用服務器來響應動態網頁JSP/SERVLET的請求。對于商業用戶來說,目前最流行的應用服務器軟件要數BEA公司開發的WebLogic,下面介紹的是WebLogic5.1的版本。 先將WebLogic解壓到/usr目錄下,需要修改WebLogic安裝目錄下的StartWebLogic.sh腳本文件來來設置你的CLASSPATH和JAVA_HOME,最后也是通過這個腳本文件來啟動服務。現在啟動的服務還不支持JSP/EJB/Servlet等技術,所以還需要修改WebLogic安裝目錄下的weblogic.properties文件。下面就詳細介紹如何來配置這個文件。 ------------------------------------------------------------------------------------------ 第98行: weblogic.system.listenPort=80 設置HTTP端口,默認是7001 第114行: weblogic.password.system=11111111 設置啟動Console的密碼,默認密碼長度為8位 第139行: weblogic.system.SSLListenPort=7002 設置SSL端口,默認是7002 第236行: weblogic.system.minPasswordLen=8 設置最小密碼長度,默認為8位 第495行-第508行: 設置你自己的RMI,命令格式如下: weblogic.system.startupClass.[virtualName]=[fullPackageName] 例如: weblogic.system.startupClass.hello=examples.rmi.hello.HelloImpl 第524行: #weblogic.ejb.deploy= # /usr/WebLogic/myserver/Your_Ejb.jar, 默認情況是不允許使用EJB,如果要使用可以把前面的注釋去掉,再設置你的EJB的路徑 第539行-第543行: 增加用戶列表,命令格式如下: weblogic.password.[username]=XXX 例如: weblogic.password.xxx=11111111 第604行: weblogic.httpd.session.enable=true 允許在服務器端使用session;session在開發電子商務程序時非常有用 第663行-第674行: 663行:#weblogic.jdbc.connectionPool.db2Pool= 664行:# url=jdbc:db2//localhost/database, 665行:# driver=COM.ibm.db2.jdbc.net.DB2Driver, 666行:# loginDelaySecs=1, 667行:# initialCapacity=4, 668行:# maxCapacity=10, 669行:# capacityIncrement=2, 670行:# allowShrinking=true, 671行:# shrinkPeriodMins=15, 672行:# refreshMinutes=10, 673行:# testTable=table, 674行:# props=user=db2admin;password=db2admin 設置你要使用到的JDBC POOL,默認情況是不允許使用,如果要使用JDBC POOL可以將前面的注釋去掉,不過首先你的JDBC驅動程序必須是在StartWebLogic.sh的CLASSPATH中已經存在的。其中663行是設置JDBC POOL的名字(如db2Pool);664和665行是注冊JDBC驅動程序以及連接的數據庫;667行為缺省的連接數;668行為連接池中最大連接數;674行為連接數據庫的用戶名和密碼 第767行: weblogic.httpd.register.*.shtml=weblogic.servlet.ServerSideIncludeServlet 允許使用SSI,即允許使用.shtml為后綴的擴展名 第790行: weblogic.httpd.register.servlets=weblogic.servlet.ServletServlet 允許使用Servlet,例如URL: http://localhost/servlets/foo/hello 則實際路徑為: /home/servlet/foo/hello.class 第814行: weblogic.httpd.documentRoot=/home/www/ 此行為設定WEB頁面的發布目錄 第831行: weblogic.httpd.servlet.classpath=/home/servlet 此行用來設置放置Servlet等class文件的目錄,當然這個目錄還必須在StartWebLogic.sh的CLASSPATH中已經存在的 第861行-第868行: 861行:#weblogic.httpd.register.*.jhtml= 862行:# weblogic.servlet.jhtmlc.PageCompileServlet 863行:#weblogic.httpd.initArgs.*.jhtml= 864行:# pageCheckSeconds=1, 865行:# packagePrefix=examples.jhtml, 866行:# compileCommand=/usr/java/bin/javac, 867行:# workingDir=/home, 868行:# verbose=true 這幾行是用來支持JHTML技術的,默認是不能使用JHTML擴展名,如果想使用JHTML,將前面的注釋去掉即可。861行后面的*.jhtml用來注冊使用擴展名為jhtml的任意文件;866行設置javac的目錄 第878行-第884行: 878行:#weblogic.httpd.register.*.jsp= 879行:# weblogic.servlet.JSPServlet 880行:#weblogic.httpd.initArgs.*.jsp= 881行:# pageCheckSeconds=1, 882行:# compileCommand=/usr/java/bin/javac, 883行:# workingDir=/home, 884行:# verbose=true 這幾行是用來支持JSP的,默認是不能使用JSP擴展名,如果想使用JSP,將前面的注釋去掉即可。878行后面的*.jsp用來注冊使用擴展名為jsp的任意文件;882行設置javac的目錄;在WebLogic中如果要運行test.jsp文件,是先將這個文件編譯成_test.class后在運行的,所以第883行設置的目錄就是用來放編譯后的.class文件用的
JRun (11 Megabytes, JSP, Servlets and EJBs) 來自www.jrun.com/
WebLogic(44 Megabytes, JSP, Servlets and EJBs) 來自www.beasys.com/
WebSphere (105 Megabytes, JSP, Servlets and EJBs) 來自www-4.ibm.com/sofeware/webservers/
以下的幾個服務器可以免費下載或者進行開發:
Blazix (1.5 Megabytes, JSP, Servlets and EJBs) 來自www.blazix.com/blazix.html
ServletExec (3.8 Megabytes, JSP and Servlets) 來自www.unifyeware.com/servletExec/
JRun (11 Megabytes, JSP, Servlets and EJBs) 來自www.jrun.com/
WebLogic(44 Megabytes, JSP, Servlets and EJBs) 來自www.beasys.com/
WebSphere (105 Megabytes, JSP, Servlets and EJBs) 來自www-4.ibm.com/sofeware/webservers/
以下的幾個服務器可以免費下載或者進行開發:
Blazix (1.5 Megabytes, JSP, Servlets and EJBs) 來自www.blazix.com/blazix.html
ServletExec (3.8 Megabytes, JSP and Servlets) 來自www.unifyeware.com/servletExec/
JRun (11 Megabytes, JSP, Servlets and EJBs) 來自www.jrun.com/
WebLogic(44 Megabytes, JSP, Servlets and EJBs) 來自www.beasys.com/
WebSphere (105 Megabytes, JSP, Servlets and EJBs) 來自www-4.ibm.com/sofeware/webservers/
要學習好一套系統首先要了解它的結構,本文詳細的介紹 WebLogic 的一些結構和特點:
WebLogic的大部分配置是在 weblogic.properties 里完成的,只要仔細的研究這個文件就可以清楚得知關于 WebLogic 的一些結構和特點,下面就對 weblogic.properties 文件里的一些配置項作一些說明:
weblogic.httpd.documentRoot=public_html/ 這就是WebLogic 的WEB 服務器的根目錄,即是目錄/weblogic/myserver/public_html/
weblogic.password.system=sdfjkdshfds 這個前文已經提到,是設置管理員密碼。
weblogic.system.listenPort=7001 這是設置 WebLogic 的 WEB 服務器端口。
weblogic.httpd.servlet.classpath=/weblogic/myserver/servletclasses 設置Servlet存放的路徑
關于Servlet
出于安全的目的,在 WebLogic 下運行的 WebLogic 必須在 weblogic.properties 里登記后才能運行,例如上文的提到Servlet http://localhost:7001/helloWorld, 它在weblogic.properties 里的登記項是 weblogic.httpd.register.helloWorld=examples.servlets.HelloWorldServlet 實際上,這個 Servlet 的實際路徑是 /weblogic/myserver/servletclasses/examples/servlets/HelloWorldServlet.class 對照一下weblogic.properties里的登記項和HelloWorldServlet.class文件的路徑,應該不難找出其登記Servlet的規律吧。
在weblogic.properties里有一下幾個Servlet的登記項:
weblogic.httpd.register.AdminEvents=admin.AdminEvents weblogic.httpd.register.AdminClients=admin.AdminClients weblogic.httpd.register.AdminConnections=admin.AdminConnections weblogic.httpd.register.AdminJDBC=admin.AdminJDBC weblogic.httpd.register.AdminLicense=admin.AdminLicense weblogic.httpd.register.AdminMain=admin.AdminMain weblogic.httpd.register.AdminProps=admin.AdminProps weblogic.httpd.register.AdminRealm=admin.AdminRealm weblogic.httpd.register.AdminThreads=admin.AdminThreads weblogic.httpd.register.AdminVersion=admin.AdminVersion
這就是管理員管理 WebLogic 用的Servlet,通過URL訪問http://localhost:7001/AdminMain,在彈出的身份驗證對話框了輸入 system 和在 weblogic.password.system= 設置的密碼,就可以進入 WebLogic 的Web管理界面進行管理。
WebLogic 是一套基于JAVA功能強大的電子商務套件,提供了許多功能強大的中間件以方便編程人員編寫的JSP、SERVLET 等電子商務應用,可以為企業提供一個完整的商務應用解決方案。對于開發人員 WebLogic 可以在 www.bea.com 免費下載一套完整的 WebLogic,并得到一個限制了 IP 的license,用于學習和開發基于這個套件的代碼。而要是需要正式的投入使用的話,那么就必須支付一定的費用獲取沒限制的license。由于這個套件基于這種發布方式,對于一般網站開發人員可以很輕易地得到 WebLogic 用于學習開發,當然投入使用是另一回事。
我獲得的 WebLogic5.10是兩個大大的zip文件,一個是WebLogic程序包,一個是資料文檔。因為是基于JAVA,雖然在下載時有區分操作系統,但是我得到的那套經過實踐發現在WINNT和LINUX都可以運行,下面主要是以LINUX的為例,WINNT的安裝方法也差不多。
安裝前準備:
在安裝前,用戶必須獲得一套對應于用戶的操作系統的JDK(在 www.sun.com 免費下載),安裝好后把WebLogic5.10的壓縮包解開,建議放在根目錄上,這樣會省去很多修改設置的麻煩,在linux下可以解在其他目錄,然后在根目錄再做一個硬連接也可以。
我的安裝的文件目錄是
/usr/local/jdk1.2/ /usr/local/weblogic/ ln -s / /usr/local/weblogic/
配置weblogic:
啟動weblogic需要執行兩個腳本文件:
linux:setEnv.sh和startWebLogic.sh
WINNT對應的是:setEnv.cmd和startWebLogic.cmd
1、weblogic.properties
打開/usr/local/weblogic/的 weblogic.properties 文件,找到這一行 weblogic.password.system= 這是設置管理員密碼用的,這個設置項不能為空,所以必須設置一個可靠的管理員密碼。 例如:weblogic.password.system=sdfjkdshfds
設置運行JSP:
# WEBLOGIC JSP PROPERTIES # ------------------------------------------------ # Sets up automatic page compilation for JSP. Adjust init args for # directory locations and uncomment to use. #weblogic.httpd.register.*.jsp=#weblogic.servlet.JSPServlet #weblogic.httpd.initArgs.*.jsp=#pageCheckSeconds=1,#compileCommand=c:/jdk1.2.1/bin/javac.exe, #workingDir=/weblogic/myserver/classfiles, #verbose=true
把那些注釋刪去,即改為
# WEBLOGIC JSP PROPERTIES # ------------------------------------------------ # Sets up automatic page compilation for JSP. Adjust init args for # directory locations and uncomment to use. weblogic.httpd.register.*.jsp=weblogic.servlet.JSPServlet weblogic.httpd.initArgs.*.jsp=pageCheckSeconds=1,compileCommand=c:/jdk1.2.1/bin/javac.exe, workingDir=/weblogic/myserver/classfiles, verbose=true
要注意的是還要配置好這一行: compileCommand=/usr/local/jdk1.2/bin/javac, 這是JDK的JAVA編譯器的路徑。
2、setEnv.sh
打開/weblogic/setEnv.sh,找到這一行 JAVA_HOME=/usr/java 改為 JAVA_HOME=/usr/local/jdk1.2/
3、 startWebLogic.sh
找到一個全是大寫的 "LINUX" 字符串,改為 "Linux",很奇怪是為何要這樣是嗎?這是因為啟動時,腳本文件調用了uname 指令來得到系統的名字,再與"LINUX" 字符串比較確認是否是linux系統,但是uname 指令來返回的系統的名字是Linux,所以我們要改一下,這應該是這個啟動腳本的一個小小的BUG,WINT就不用那么麻煩了。
運行weblogic:
經過簡單的配置就試運行了。
在目錄/weblogic/下執行
. ./setEnv.sh (大家請留意,我這里有兩個 ".",因為我們需要在當前的shell下執行這個腳本 )
./startWebLogic.sh
當看到成功啟動 WebLogic 的信息時,說明啟動成功了。
服務器簡單的測試:
WebLogic 默認的WEB端口為7001,我們可以在打開一個瀏覽器輸入地址 http://localhost:7001/ 測試是否能連接得上。
Servlet的測試
如果能連得上得話,那么就可以進行下一步的Servlet的測試,在瀏覽器輸入地址 http://localhost:7001/helloWorld 這個就是WebLogic Servlet的演示(至于怎樣安裝 Servlet請看下文)
JSP的測試
在目錄 /weblogic/myserver/public_html/下建立一個名為test.jsp的文件
test.jsp
<%
Out.print("test JSP");
%>
在瀏覽器輸入地址 http://localhost:7001/test.jsp 測試能否看到正確的輸出"test JSP"的信息。
使用Hibernate的一個完整例子 |
配置 1、 下載安裝Tomcat,并且下載Hibernate的運行環境(主要包含一些JAR包)。
2、 把要使用的數據庫的JDBC驅動程序拷貝到%TOMCAT_HOME%\common\lib目錄下。筆者使用的是MYSQL,對應的驅動程序的JAR包為mm.mysql-2.0.4-bin.jar。
3、 在Tomcat的Webapps目錄下新建一個Web應用,名字為hibernate。
4、 把Hibernate提供的hibernate2.jar和一些第三方的運行庫拷貝到hibernate\WEB\INF\lib目錄下。(這些第三方的運行庫包含在下載的Hibernate lib目錄下)
5、 在%TOMCAT_HOME%\conf\server.xml中Web應用和數據源。在server.xml中加入以下的配置描述。 例程1 配置web應用
<Context path="/hibernate" docBase="hibernate" debug="0" reloadable="true" crossContext="true"> <Resource name="jdbc/hibernate" auth="Container" type="javax.sql.DataSource"/> <ResourceParams name="jdbc/hibernate"> <parameter> <name>factory</name> <value>org.apache.commons.dbcp.BasicDataSourceFactory</value> </parameter> <parameter> <name>driverClassName</name> <value>org.gjt.mm.mysql.Driver</value> </parameter> <parameter> <name>url</name> <value>jdbc:mysql:///test</value> </parameter> <parameter> <name>username</name> <value>root</value> </parameter> <parameter> <name>password</name> <value></value> </parameter> <parameter> <name>maxActive</name> <value>20</value> </parameter> <parameter> <name>maxIdle</name> <value>10</value> </parameter> <parameter> <name>maxWait</name> <value>-1</value> </parameter> </ResourceParams> </Context>
在這里,配置了一個名為hibernate的Web應用,并且配置了一個數據源,數據源的JNDI名稱為jdbc/hibernate。您需要根據情況修改數據源的鏈接屬性。
6、 下一步就是書寫Hibernate的配置描述符。可以使用XML的配置描述,也可以使用基于屬性的配置描述。在這里使用基于XML的配置描述。在hibernate\WEB-INF\classes目錄下新建一個hibernate.cfg.xml文件。然后加入例程2所示的內容。
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" " http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd";>
<hibernate-configuration> <session-factory> <property name="connection.datasource">java:comp/env/jdbc/hibernate</property> <property name="show_sql">false</property> <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!-- Mapping files -->
</session-factory>
</hibernate-configuration>
注意connection.datasource屬性必須和server.xml中配置的數據源的屬性一樣。如果不是使用MYSQL,那么需要更改dialect屬性。
到現在,配置基本完成,下面我們來開發一個最簡單的應用。
開發持久對象、編寫映射描述 我們使用hibernate來封裝一個簡單的數據表。這個表的名字為Courses,它有兩個字段,一個是ID,它是Courses表的主鍵;另一個是name,表示Courses的名字。在數據庫中使用以下的腳本來創建這個表:
create table Courses(CourseId varchar(32) not null, name varchar(32), constraint pk_Courses primary key (CourseId) );
接下來的任務就是為Courses表書寫持久對象,如例程3所示。
例程3 Courses的持久對象(Courses.java)
package com.hellking.study.hibernate;
import java.util.Set;
/** *在hibernate中代表了Course表的類。 */ public class Course { /**每個屬性和表的一個字段對應**/ private String id; private String name;
/**students表示course中的學生,在后面才會用到,暫時不管**/ private Set students;
/**屬性的訪問方法**/ public void setId(String string) { id = string; }
public String getId() { return id; }
public void setName(String name) { this.name=name; } public String getName() { return this.name; } public void setStudents(Set stud) { this.students=stud; } public Set getStudents() { return this.students; } }
可以看出,在Course類中也包含了兩個屬性,id和name,它的屬性和表Courses的字段是一一對應的,并且類型一致。 書寫好了持久對象,接下來的任務就是書寫對象、關系映射描述。在hibernate\WEB-INF\classes目錄下新建一個Course.hbm.xml描述文件,內容如例程4所示。 例程4 Course.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" " http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd";>
<hibernate-mapping> <class name="com.hellking.study.hibernate.Course" table="Courses" dynamic-update="false" >
<id name="id" column="CourseId" type="string" unsaved-value="any" > <generator class="assigned"/> </id>
<property name="name" type="string" update="true" insert="true" column="Name" /> </class> </hibernate-mapping>
在Course.hbm.xml映射文件中,指定了要映射的類和映射的表,并且指定了表的各個字段和Java對象中各個字段的映射關系,比如Course對象中的id屬性對應了Courses表的courseId字段。
接下來的任務就是在hibernate.cfg.xml中指定這個映射關系。如下所示:
<session-factory> … <!-- Mapping files --> <mapping resource="Course.hbm.xml"/> </session-factory>
編寫業務邏輯 到此,我們已經封裝了一個名為Courses的表,并且配置完成。接下來的任務就是在Web應用開發中使用它們,為了演示在Hibernate中對數據庫的不同類型的操作,我們開發的Web應用有以下的功能:
增加一個Course;
刪除一個Course;
按照Course的名字進行模糊搜索;
查看系統中所有的Course。
雖然我們可以直接在JSP中使用hibernate,但是往往我們不這樣,而是把這些業務邏輯封裝在JavaBean中,然后在JSP中通過調用JavaBean以訪問Hibernate封裝的對象。
由于訪問通過使用hibernate有一些共性的操作,在這里我們把這些共性的操作封裝在一個專門的類中,這樣其它的類可以繼承它,如例程5所示。
例程5 HibernateBase.java
package com.hellking.study.hibernate;
import net.sf.hibernate.*; import net.sf.hibernate.cfg.*; import java.util.*; import java.io.IOException; import java.io.PrintWriter;
public abstract class HibernateBase { protected SessionFactory sessionFactory;//會話工廠,用于創建會話 protected Session session;//hibernate會話 protected Transaction transaction; //hiberante事務
public HibernateBase()throws HibernateException { this.initHibernate(); } // 幫助方法 protected void initHibernate() throws HibernateException {
// 裝載配置,構造SessionFactory對象 sessionFactory = new Configuration().configure().buildSessionFactory(); }
/** *開始一個hibernate事務 */ protected void beginTransaction() throws HibernateException {
session = sessionFactory.openSession(); transaction = session.beginTransaction(); }
/** *結束一個hibernate事務。 */ protected void endTransaction(boolean commit) throws HibernateException {
if (commit) { transaction.commit(); } else { //如果是只讀的操作,不需要commit這個事務。 transaction.rollback(); } session.close(); } }
下面編寫業務邏輯類,新建一個名為CourseBean的JavaBean,并且CourseBean繼承HibernateBase類,代碼如例程6所示。
例程6 CourseBean.java
package com.hellking.study.hibernate;
import net.sf.hibernate.*; import net.sf.hibernate.cfg.*; import java.util.*;
/** *和course相關的業務邏輯 */ public class CourseBean extends HibernateBase { public CourseBean()throws HibernateException { super(); } /** *增加一個Course */ public void addCourse(Course st)throws HibernateException { beginTransaction(); session.save(st); endTransaction(true); }
/** *查詢系統中所有的Course,返回的是包含有Course持久對象的Iterator。 */ public Iterator getAllCourses()throws HibernateException { String queryString = "select courses from Course as courses"; beginTransaction(); Query query = session.createQuery(queryString); Iterator it= query.iterate(); return it; }
/** *刪除給定ID的course */ public void deleteCourse(String id)throws HibernateException { beginTransaction(); Course course=(Course)session.load(Course.class,id); session.delete(course); endTransaction(true); }
/** *按course的名字進行模糊查找,返回的是包含有Course持久對象的Iterator。 */ public Iterator getSomeCourse(String name)throws HibernateException { String queryString = "select c from Course as c where c.name like :name" beginTransaction(); Query query = session.createQuery(queryString); query.setString("name", "%"+name+"%"); Iterator it= query.iterate(); return it; } }
在CourseBean封裝了4個業務方法,你可以根據情況增加其它的業務方法。在CourseBean中,通過Hibernate來操作潛在的數據庫資源。
要保存Course數據到數據庫,可以通過:
session.save(Course);
方法來保存,它相當于使用在JDBC中執行以下語句:
Connection con=… Statement stmt=con.createStatement(); stmt.executeUpdate("insert into courses values('"+course.getId(),+"','"+course.getName()+"')"); con.close();
可以看出,通過使用Hibernate,可以大大減少數據訪問的復雜度。
在JSP中調用業務邏輯 添加數據 CourseBean這個業務對象封裝了和Hibernate的交互關系,從而使JSP和Hibernate關系的解藕。我們來看測試主頁面的部分代碼,如例程7所示。
例程7 測試Hibernate開發的應用(course.jsp)
<%@ page import="java.sql.*,java.util.*" errorPage="error.jsp"%> <jsp:useBean id="course" class="com.hellking.study.hibernate.Course" scope="page"> <jsp:setProperty name="course" property="*"/> </jsp:useBean> <jsp:useBean id="courseBusiness" class="com.hellking.study.hibernate.CourseBean" scope="page"/> <html><body><center> <% try { if(course.getId().equals(null)||course.getId().equals("")); else courseBusiness.addCourse(course);
%> 成功添加了Course:<br> name:<%=course.getName()%> Id:<%=course.getId()%> <% } catch(Exception e) { } %>
<hr> <br>::增加一個course::<br> <form action="course.jsp" method="get" name="add"> id:<input type=text name="id"><br> name:<input type=text name="name"><br> <input type=submit value="submit"><br> </form> <hr> ::按名字模糊查找::<br> <form action="queryCourse.jsp" method="get" name="queryByName"> name:<input type=text name="name"><br> <input type=submit value="query"><br> </form> <hr> ::刪除一個Course::<br> <form action="deleteCourse.jsp" method="get" name="queryByName"> id:<input type=text name="id"><br> <input type=submit value="delete"><br> </form> <hr> <a href=viewAll.jsp>::查看所有Course::<a> </body> </html>
首先通過一個值對象Course(這個類正好是Hibernate使用的持久對象,這里作為值對象來傳遞數據)接收獲得的參數,然后CourseBean的addCourse(Course)方法把數據保存到數據庫。可以看出,通過使用Hibernate,把數據從表單中添加到數據庫非常簡單。
查詢 下面來看模糊查找的JSP代碼,如例程8所示。 例程8 按名字模糊查找Course
<%@ page import="java.sql.*,java.util.*,com.hellking.study.hibernate.Course" errorPage="error.jsp"%> <jsp:useBean id="courseBusiness" class="com.hellking.study.hibernate.CourseBean" scope="page"/> … <% try { Iterator it=courseBusiness.getSomeCourse((String)request.getParameter("name")); while(it.hasNext()) { Course temp=(Course)it.next(); out.println("<tr><td>"+temp.getId()+"</td>"); out.println("<td>"+temp.getName()+"</td></tr>"); } } catch(Exception e) { out.println(e.getMessage()); } %> ….
它實際上調用的是CourseBean的Iterator getSomeCourse(String name)方法。我們來回顧一下這個方法中的代碼:
/** *按course的名字進行模糊查找 */ public Iterator getSomeCourse(String name)throws HibernateException { String queryString = "select c from Course as c where c.name like :name" beginTransaction(); Query query = session.createQuery(queryString); query.setString("name", "%"+name+"%"); Iterator it= query.iterate(); return it; }
在查詢前,首先調用beginTransaction方法啟動新的Hibernate事務,然后創建一個Query對象,在創建這個對象時,同時指定查詢的語句。
注意,在查詢語句:
select c from Course as c where c.name like :name"
中,它雖然和普通的SQL語句相似,但是不同,在數據庫中,使用的表的名字是Courses,而在這個查詢語句中使用的是Course,它和持久對象的名字一致,也就是說,這個查詢的概念是查詢持久對象,而不是數據庫的記錄。
創建了查詢對象Query后,需要設置查詢的參數,它和在JDBC中PreparedStatement對象中設置參數的方法相似。通過"Iterator it= query.iterate()"語句來執行查詢,并且返回一個Iterator對象。在這里使用了Hibernate提供的查詢機制,一般的JDBC查詢返回的是ResultSet對象,而這里返回的是包含了CourseBean對象的Iterator。
要查詢系統中所有的Course,也同樣非常簡單,可以通過例程9所示的代碼實現。
例程9 查詢數據庫中所有的Course
… <jsp:useBean id="courseBusiness" class="com.hellking.study.hibernate.CourseBean" scope="page"/> … <% try { Iterator it=courseBusiness.getAllCourses(); while(it.hasNext()) { Course temp=(Course)it.next(); out.println("<tr><td>"+temp.getId()+"</td>"); out.println("<td>"+temp.getName()+"</td></tr>"); } } catch(Exception e) { out.println(e.getMessage()); } %> …
實際上調用的是CourseBean的getAllCourses方法,它和getSomeCourse方法機制一樣,就不再介紹了。
刪除數據 在JSP中,使用以下的代碼來執行刪除操作。 例程10 刪除數據庫中Courses表的記錄
<jsp:useBean id="courseBusiness" class="com.hellking.study.hibernate.CourseBean" scope="page"/> … 刪除id為:<%=request.getParameter("id")%>的course::::<br>
<% try { courseBusiness.deleteCourse(request.getParameter("id")); out.println("刪除成功"); } catch(Exception e) { out.println("不存在這個記錄"); } %>
我們來看CourseBean中執行刪除操作的具體代碼:
/** *刪除給定ID的course */ public void deleteCourse(String id)throws HibernateException { beginTransaction(); Course course=(Course)session.load(Course.class,id); session.delete(course); endTransaction(true); }
在這個方法中,首先開始一個事務,然后通過session.load(Course.class,id)方法來裝載指定ID的持久對象,接下來通過"session.delete(course)"來刪除已經裝載的course,并且結束Hibernate事務。
總結 下面總結一下使用Hibernate的開發過程:
1、 配置Hibernate(一次即可); 2、 確定數據表;
3、 創建持久對象;
4、 編寫對象和數據表的映射描述;
5、 編寫和業務邏輯。
實際上,上面的過程和使用EJB沒有什么區別:在使用EJB時,首先當然也是配置環境,初始化數據表;然后創建實體Bean(對象于Hibernate的持久對象);接下來編寫部署描述符(ejb-jar.xml,廠商專有的部署描述),在這些部署描述符里,指定了EJB和數據表的映射關系,如果多個實體Bean存在關聯關系,需要描述它們之間的關系,這些描述對應于Hibernate中持久對象的描述,如Course.hbm.xml;往往我們并不在應用程序中直接操作實體Bean,而是通過業務對象(如會話Bean)來操作,這里的會話Bean可以簡單的和Hibernate中執行業務邏輯的JavaBean對應。這里只是簡單的類比,不是絕對的,比如我們同樣可以在會話Bean中訪問Hibernate持久對象,也就是說使用Hibernate,同樣可以把業務邏輯放在會話Bean中。
通過本文的學習,相信讀者對Hibernate已經有了初步的認識,并且能夠使用Hibernate開發簡單的應用。在下一篇中,我們將學習怎么使用Hibernate來為復雜的數據表進行映射,并且維護它們之間的關系。
參考資料
http://www.apache.org 下載Tomcat。 Hibernate的官方網站, http://hibernate.bluemars.net/ ,包含了Hibernate最新資料。
Hibernate中文論壇,hibernate.fankai.com包含了Hibernate較多的參考資料。
包含了Hibernate技術討論網站,www.jdon.com,
于Hibernate、JDO、CMP等技術的熱烈討論1:
http://www.jdon.com/jive/thread.jsp?forum=16&thread=6062&start=0&msRange=15
于Hibernate、JDO、CMP等技術的熱烈討論2:
http://www.theserverside.com/discussion/thread.jsp?thread_id=19732
Hibernate2 Reference document.tion,可以從Hibernate官方網站獲得,非常好的參考資料。
Hibernate In Action,一本非常專業的Hibernate參考書,由Hibernate項目主要開發人員Gavin King 等著,Manning出版社出版。您可以從 http://www.theserverside.com 獲得本書的部分章節。
|
Hibernate查詢語言:HQL
HQL:Hibernate Qusery Language,如果你已經熟悉它,就會發現它跟SQL非常相像。不過 你不要被表面的假象迷惑,HQL是面向對象的(OO,用生命的眼光看待每一個對象,他們是如此 鮮活)。如果你對JAVA和SQL語句有一定了解的話,那么HQL對你簡直易如反掌,你完全可以利用在公車上的時間掌握它。 以下從幾個方面進行慢慢深入: 1。大小些敏感 大家知道Query是對大小寫不敏感的,但是在HQL(前面提到它是OO的)中那么對象類的名稱和屬性確實大小寫敏感的(符合java編程語法)。 如:sElect cat.name from Cat as cat和select cat.name from Cat as cat是一樣的 但是: sElect cat.name from CAT as cat和select cat.name from Cat as cat確實不一樣的。 2。from語句 最簡單的: from eg.Cat 它只是簡單的返回所有eg.Cat的實例 通常我們此時會為eg.Cat其個別名,因為在query的其余部分可能會用到(參看上邊關于大小寫 敏感時的例子情形),如: from eg.Cat as cat 這里as可以省略。 上邊只是單表查詢,多表的情況如下寫法: from eg.Cat,eg.Dog from eg.Cat as cat,eg.Dog as dog 3。join相關 (inner) join left (outer) join right (outer) join full join HQL同樣對SQL中的這些特性支持 下面插播一個小話題,關于上邊的那些特性,我一直都沒怎么用,今天既然說到這里,就想 把上邊的幾個特性的用法說一下,也算對自己的一個補充: 假設有兩個表:部門、員工,下面列舉一些數據: 員工(Employee): ID Name DepNo 001 Jplateau 01 002 Jony 01 003 Camel 02 部門(Department): ID Name 01 研發部 02 營銷部 在Hibernate中我們操縱的都是對象,所以我們操縱的是部門類和員工類 1).(inner) join select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name as name2 from Employee as employee join Department as department on employee.DepNo= department.ID (注意到條件語句我用on 沒有用where) 那么執行結果是什么呢? id1 name1 id2 name2 ++++++++++++++++++++++++++++++++++++++ 001 Jplateau 01 研發部 002 Jony 01 研發部 2).left (outer) join select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name as name2 from Employee as employee left join Department as department on employee.DepNo= department.ID 那么執行結果又該是什么呢? id1 name1 id2 name2 ++++++++++++++++++++++++++++++++++++++ 001 Jplateau 01 研發部 002 Jony 01 研發部 003 Camel null null {就是說此時我要已第一個表的記錄多少為準,第二個表中沒有相應紀錄的時候填充null} 3). right (outer) join select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name as name2 from Employee as employee right join Department as department on employee.DepNo= department.ID 那么執行結果又該是什么呢? id1 name1 id2 name2 ++++++++++++++++++++++++++++++++++++++ 001 Jplateau 01 研發部 002 Jony 01 研發部 null null 02 營銷部 {就是說此時我要已第二個表的記錄多少為準,第一個表中沒有相應紀錄的時候填充null} 4。select語句 就是要確定你要從查詢中返回哪些對象或者哪些對象的屬性。寫幾個例子吧: select employee form Employee as employee select employee form Employee as employee where employee.Name like 'J%' select employee.Name form Employee as employee where employee.Name like 'J%' select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name as name2 from Employee as employee right join Department as department on employee.DepNo= department.ID select elements(employee.Name) from Employee as employee (不明白elements到底是做什么用的?望給于說明) 等等 5。數學函數 JDO目前好像還不支持此類特性。 avg(...), sum(...), min(...), max(...)
count(*)
count(...), count(distinct ...), count(all...) 其用法和SQL基本相同 select distinct employee.name from Employee as employee select count(distinct employee.name),count(employee) from Employee as employee 6。polymorphism (暫時不知道如何解釋?) from com.test.Animal as animal 不光得到所有Animal得實例,而且可以得到所有Animal的子類(如果我們定義了一個子類Cat) 一個比較極端的例子 from java.lang.Object as o 可以得到所有持久類的實例 7。where語句 定義查詢語句的條件,舉幾個例子吧: from Employee as employee where employee.Name='Jplateau' from Employee as employee where employee.Name like 'J%' from Employee as employee where employee.Name like '%u' 在where語句中“=”不光可以比較對象的屬性,也可以比較對象,如: select animal from com.test.Animal as animal where animal.name=dog 8。表達式 在SQL語句中大部分的表達式在HQL中都可以使用: mathematical operators +, -, *, /
binary comparison operators =, >=, <=, <>, !=, like
logical operations and, or, not
string concatenation ||
SQL scalar functions like upper() and lower() Parentheses ( ) indicate grouping
in, between, is null
JDBC IN parameters ?
named parameters :name, :start_date, :x1 (這種應該是另一種"?"的變通解決方法)
SQL literals 'foo', 69, '1970-01-01 10:00:01.0'
Java public static final constants eg.Color.TABBY 其他不必解釋了,在這里我只想對查詢中的參數問題說明一下: 大家知道在SQL中進行傳遞參數進行查詢的時候,我們通常用PreparedStatement,在語句中寫一大堆的“?”, 在hql中也可以用這種方法,如: List mates = sess.find( "select employee.name from Employee as employee " + "where employee.Name=? ", name, Hibernate.STRING ); (說明:上面利用Session里的find方法,在hibernate的api Session中重載了很多find方法,它可以滿足你多種形式的查詢) 上邊是一個參數的情形,這種情況下緊接著引入參數和定義參數的類型,當為多個參數,調用另一個find方法,它的后兩個 參數都是數組的形式。 還有另外一種方法來解決上邊的問題,JDO也有這樣的方法,不過和hibernate的表現形式上有差別,但他們兩個骨子里卻是 一樣的,如: Query q = sess.createQuery("select employee.name from Employee as employee where employee.Name=:name"); q.setString("name", "Jplateau"); //當有多個參數的時候在此逐一定義 Iterator employees = q.iterate(); 9。order 語句 和sql語句沒什么差別,如: select employee.name from Employee as employee where employee.Name like 'J%' order by employee.ID desc (或者asc) 10。group by 語句 同樣和sql語句沒什么差別,如: select employee.name,employee.DepNo from Employee as employee group by employee.DepNo select foo.id, avg( elements(foo.names) ), max( indices(foo.names) ) from eg.Foo foo group by foo.id {Note: You may use the elements and indices constructs inside a select clause, even on databases with no subselects.} 誰幫我解釋一下上邊兩句,謝過! 11。子查詢 hibernate同樣支持子查詢,寫幾個例子: from eg.Cat as fatcat where fatcat.weight > ( select avg(cat.weight) from eg.DomesticCat cat )
Configuration的其他用法
Configuration的configure ()方法還支持帶參數的訪問方式,你可以指定hbm.xml文件的位置,而不是使用默認的classpath下面的hibernate.cfg.xml這種方式,例如:
Configuration cfg = new Configuration().configure("myexample.xml"); | 同時Configuration還提供了一系列方法用來定制hibernate的加載配置文件的過程,讓你的應用更加靈活,常用的是以下幾種:
addProperties(Element) addProperties(Properties) setProperties(Properties) setProperty(String, String) | 通過以上幾個方法,除了使用默認的hibernate.properties文件,你還可以提供多個.properties配置文件,使用Hibernate的時候根據不同的情況使用不同的配置文件,例如:
Properties properties = Properties.load("my.properties"); Configuration config = new Configuration().setProperties(properties).configure(); | 除了指定.properties文件之外,還可以指定.hbm.xml文件,下面列出幾個常用的方法:
addClass(Class) addFile(File) addFile(String) addURL(URL) | 前面我們已經講了,configure()方法默認是通過訪問hibernate.cfg.xml的<mapping>元素來加載我們提供的.hbm.xml文件,上面列出的方法可以直接指定hbm.xml文件,例如addClass()方法可以直接通過指定class來加載對應的映射文件,hibernate會將提供的class的全名(包括package)自動轉化為文件路徑,如net.sf.hibernate.examples.quickstart.Cat.class對應了net/sf/hibernate/examples/quickstart/Cat.hbm.xml,還可以用addFile方法直接指定映射文件。
例一:
Configuration config = new Configuration().addClass(Cat.class); | 例二:
Configuration config = new Configuration().addURL(Configuration.class.getResource ("Cat.hbm.xml")); | 例三:
Configuration config = new Configuration().addFile("Cat.hbm.xml"); | 5、總結
Configuration提供的這些方法的好處如下:
1) 一個應用中往往有很多.hbm.xml映射文件,開發的過程中如果只是為了測試某個或幾個Java PO(Persistence Object),我們沒有必要把所有的.hbm.xml都加載到內存,這樣可以通過addClass或者addFile直接,顯得非常靈活。
2) 學習Hibernate的過程中,往往需要通過練習來體會Hibernate提供的各種特征,而很多特征是需要修改配置文件的,如果要觀察相同的代碼在不同的特征下的表現,就需要手工改配置文件,這樣太麻煩了,而且容易出錯,我們可以提供多個配置文件,每個配置文件針對需要的特征而配置,這樣我們在調用程序的時候,把不同的配置文件作為參數傳遞進去,而程序代碼里面使用setProperties和addFile指定傳入的配置文件參數就可以了。
3) 在單元測試中,特別是在集成測試里面,整個過程是自動化的,我們不能手工干預測試過程,往往需要準備多個配置文件針對不同的測試案例,這個時候setProperties和addFile方法就顯得特別有用了,在不同的測試案例中用這些方法來指定相應的配置文件,這樣就可以做到自動化測試,保證了持續性。
發表者付: 做軟件到一定層次了,就要考慮到設計了,設計了很久,就是不系統,系統的設計需要一個記錄,記錄就用文檔,那么對項目所有包括技術上的設計都記錄下來,我們就可以理解為軟件的概要設計了。
在需求明確、準備開始編碼之前,要做概要設計,而詳細設計可能大部分公司沒有做,有做的也大部分是和編碼同步進行,或者在編碼之后。因此,對大部分的公司來說,概要設計文檔是唯一的設計文檔,對后面的開發、測試、實施、維護工作起到關鍵性的影響。 一、問題的提出 概要設計寫什么?概要設計怎么做? 如何判斷設計的模塊是完整的? 為什么說設計階段過于重視業務流程是個誤區? 以需求分析文檔還是以概要設計文檔來評估開發工作量、指導開發計劃準確? 結構化好還是面向對象好? 以上問題的答案請在文章中找。 二、概要設計的目的 將軟件系統需求轉換為未來系統的設計; 逐步開發強壯的系統構架; 使設計適合于實施環境,為提高性能而進行設計; 結構應該被分解為模塊和庫。 三、概要設計的任務 制定規范:代碼體系、接口規約、命名規則。這是項目小組今后共同作戰的基礎,有了開發規范和程序模塊之間和項目成員彼此之間的接口規則、方式方法,大家就有了共同的工作語言、共同的工作平臺,使整個軟件開發工作可以協調有序地進行。 總體結構設計: 功能(加工)->模塊:每個功能用那些模塊實現,保證每個功能都有相應的模塊來實現; 模塊層次結構:某個角度的軟件框架視圖; 模塊間的調用關系:模塊間的接口的總體描述; 模塊間的接口:傳遞的信息及其結構; 處理方式設計:滿足功能和性能的算法 用戶界面設計; 數據結構設計: 詳細的數據結構:表、索引、文件; 算法相關邏輯數據結構及其操作; 上述操作的程序模塊說明(在前臺?在后臺?用視圖?用過程?······) 接口控制表的數據結構和使用規則 其他性能設計。 四、概要設計寫什么 結構化軟件設計說明書結構(因篇幅有限和過時嫌疑,在此不作過多解釋) 任務:目標、環境、需求、局限; 總體設計:處理流程、總體結構與模塊、功能與模塊的關系; 接口設計:總體說明外部用戶、軟、硬件接口;內部模塊間接口(注:接口≈系統界面) 數據結構:邏輯結構、物理結構,與程序結構的關系; 模塊設計:每個模塊“做什么”、簡要說明“怎么做”(輸入、輸出、處理邏輯、與其它模塊的接口,與其它系統或硬件的接口),處在什么邏輯位置、物理位置; 運行設計:運行模塊組合、控制、時間; 出錯設計:出錯信息、處錯處理; 其他設計:保密、維護; OO軟件設計說明書結構 1 概述 系統簡述、軟件設計目標、參考資料、修訂版本記錄 這部分論述整個系統的設計目標,明確地說明哪些功能是系統決定實現而哪些時不準備實現的。同時,對于非功能性的需求例如性能、可用性等,亦需提及。需求規格說明書對于這部分的內容來說是很重要的參考,看看其中明確了的功能性以及非功能性的需求。 這部分必須說清楚設計的全貌如何,務必使讀者看后知道將實現的系統有什么特點和功能。在隨后的文檔部分,將解釋設計是怎么來實現這些的。 2 術語表 對本文檔中所使用的各種術語進行說明。如果一些術語在需求規格說明書中已經說明過了,此處不用再重復,可以指引讀者參考需求說明。 3 用例 此處要求系統用用例圖表述(UML),對每個用例(正常處理的情況)要有中文敘述。 4 設計概述 4.1 簡述 這部分要求突出整個設計所采用的方法(是面向對象設計還是結構化設計)、系統的體系結構(例如客戶/服務器結構)以及使用到的相應技術和工具(例如OMT、Rose) 4.2 系統結構設計 這部分要求提供高層系統結構(頂層系統結構、各子系統結構)的描述,使用方框圖來顯示主要的組件及組件間的交互。最好是把邏輯結構同物理結構分離,對前者進行描述。別忘了說明圖中用到的俗語和符號。 4.3 系統界面 各種提供給用戶的界面以及外部系統在此處要予以說明。如果在需求規格說明書中已經對用戶界面有了敘述,此處不用再重復,可以指引讀者參考需求說明。如果系統提供了對其它系統的接口,比如說從其它軟件系統導入/導出數據,必須在此說明。 4.4 約束和假定 描述系統設計中最主要的約束,這些是由客戶強制要求并在需求說明書寫明的。說明系統是如何來適應這些約束的。 另外如果本系統跟其它外部系統交互或者依賴其它外部系統提供一些功能輔助,那么系統可能還受到其它的約束。這種情況下,要求清楚地描述與本系統有交互的軟件類型以及這樣導致的約束。 實現的語言和平臺也會對系統有約束,同樣在此予以說明。 對于因選擇具體的設計實現而導致對系統的約束,簡要地描述你的想法思路,經過怎么樣的權衡,為什么要采取這樣的設計等等。 5 對象模型 提供整個系統的對象模型,如果模型過大,按照可行的標準把它劃分成小塊,例如可以把客戶端和服務器端的對象模型分開成兩個圖表述。在其中應該包含所有的系統對象。這些對象都是從理解需求后得到的。要明確哪些應該、哪些不應該被放進圖中。所有對象之間的關聯必須被確定并且必須指明聯系的基數。聚合和繼承關系必須清楚地確定下來。每個圖必須附有簡單的說明。 6 對象描述 在這個部分敘述每個對象的細節,它的屬性、它的方法。在這之前必須從邏輯上對對象進行組織。你可能需要用結構圖把對象按子系統劃分好。 為每個對象做一個條目。在系統對象模型中簡要的描述它的用途、約束(如只能有一個實例),列出它的屬性和方法。如果對象是存儲在持久的數據容器中,標明它是持久對象,否則說明它是個臨時對象(transient object)。 對每個對象的每個屬性詳細說明:名字、類型,如果屬性不是很直觀或者有約束(例如,每個對象的該屬性必須有一個唯一的值或者值域是有限正整數等)。 對每個對象的每個方法詳細說明:方法名,返回類型,返回值,參數,用途以及使用的算法的簡要說明(如果不是特別簡單的話)。如果對變量或者返回值由什么假定的話,Pre-conditions和Post-conditions必須在此說明。列出它或者被它調用的方法需要訪問或者修改的屬性。最后,提供可以驗證實現方法的測試案例。 7 動態模型 這部分的作用是描述系統如何響應各種事件。一般使用順序圖和狀態圖。 確定不同的場景(Scenario)是第一步,不需要確定所有可能的場景,但是必須至少要覆蓋典型的系統用例。不要自己去想當然地創造場景,通常的策略是描述那些客戶可以感受得到的場景。 7.1 場景(Scenarios) 對每個場景做一則條目,包括以下內容: 場景名:給它一個可以望文生義的名字 場景描述:簡要敘述場景是干什么的以及發生的動作的順序。 順序圖:描述各種事件及事件發生的相對時間順序。 7.2 狀態圖 這部分的內容包括系統動態模型重要的部分的狀態圖。可能你想為每個對象畫一個狀態圖,但事實上會導致太多不期望的細節信息,只需要確定系統中一些重要的對象并為之提供狀態圖即可。 8 非功能性需求 五、概要設計怎么做 結構化軟件設計方法: 詳細閱讀需求規格說明書,理解系統建設目標、業務現狀、現有系統、客戶需求的各功能說明; 分析數據流圖,弄清數據流加工的過程; 根據數據流圖決定數據處理問題的類型(變換型、事務型、其他型); 通過以上分析,推導出系統的初始結構圖; 對初始結構圖進行改進完善:所有的加工都要能對應到相應模塊(模塊的完整性在于他們完成了需求中的所有加工),消除完全相似或局部相似的重復功能(智者察同),理清模塊間的層次、控制關系,減少高扇出結構,隨著深度增大扇入,平衡模塊大小。 由對數據字典的修改補充完善,導出邏輯數據結構,導出每種數據結構上的操作,這些操作應當屬于某個模塊。 確定系統包含哪些應用服務系統、客戶端、數據庫管理系統; 確定每個模塊放在哪個應用服務器或客戶端的哪個目錄、哪個文件(庫),或是在數據庫內部建立的對象。 對每個篩選后的模塊進行列表說明。 對邏輯數據結構進行列表說明。 根據結構化軟件設計說明書結構對其他需要說明的問題進行補充說明,形成概要設計說明書。 OO軟件設計方法: 在OOA基礎上設計對象與類:在問題領域分析(業務建模和需求分析)之后,開始建立系統構架。 第一步是抽取建立領域的概念模型,在UML中表現為建立對象類圖、活動圖和交互圖。對象類就是從對象中經過“察同”找出某組對象之間的共同特征而形成類: 對象與類的屬性:數據結構; 對象與類的服務操作:操作的實現算法; 對象與類的各外部聯系的實現結構; 設計策略:充分利用現有的類; 方法:繼承、復用、演化; 活動圖用于定義工作流,主要說明工作流的5W(Do What、Who Do、When Do、Where Do、Why Do)等問題,交互圖把人員和業務聯系在一起是為了理解交互過程,發現業務工作流中相互交互的各種角色。 第二步是構建完善系統結構:對系統進行分解,將大系統分解為若干子系統,子系統分解為若干軟件組件,并說明子系統之間的靜態和動態接口,每個子系統可以由用例模型、分析模型、設計模型、測試模型表示。軟件系統結構的兩種方式:層次、塊狀 層次結構:系統、子系統、模塊、組件(同一層之間具有獨立性); 塊狀結構:相互之間弱耦合 系統的組成部分: 問題論域:業務相關類和對象(OOA的重點); 人機界面:窗口、菜單、按鈕、命令等等; 數據管理:數據管理方法、邏輯物理結構、操作對象類; 任務管理:任務協調和管理進程; 第三步是利用“4+1”視圖描述系統架構:用例視圖及劇本;說明體系結構的設計視圖;以模塊形式組成包和層包含概要實現模型的實現視圖;說明進程與線程及其架構、分配和相互交互關系的過程視圖;說明系統在操作平臺上的物理節點和其上的任務分配的配置視圖。在RUP中還有可選的數據視圖。 第四步是性能優化(速度、資源、內存)、模型清晰化、簡單化(簡單就是享受)。 六、概要設計的原則 總體原則和方法:由粗到細的原則,互相結合的原則,定性分析和定量分析相結合的方法,分解和協調的方法和模型化方法。 要系統考慮系統的一般性、關聯性、整體性和層次性。 分解協調:目的是為了創造更好的系統。系統分解是指將一個復雜的系統分解為若干個子系統,系統協調一是系統內協調,即根據系統的總結構、總功能、總任務和總目標的要求,使各個子系統之間互相協調配合,在各個子系統局部優化基礎上,通過內部平衡的協調控制,實現系統的整體優化; 屏蔽抽象:從簡單的框架開始,隱含細節; 一致性:統一的規范、統一的標準、統一的文件模式; 每個模塊應當有一個統一命名的容易理解的名字; 編碼:由外向內(界面->核心); 面向用戶:概要設計是對于按鈕按下后系統“怎么做”的簡要說明; 模塊、組件的充分獨立性、封閉性; 同時考慮靜態結構與動態運行; 每個邏輯對象都應當說明其所處物理對象(非一一對應); 每個物理對象都有合適的開發人員,并且利于分工與組裝。(詳細說明見本人另一篇文章:系統構架設計應考慮的因素); 確立每個構架視圖的整體結構:視圖的詳細組織結構、元素的分組以及這些主要分組之間的接口; 軟件構架與使用的技術平臺密切相關,目前常用的平臺有J2EE、.NET、CORBA等等,因此具體的軟件構架人員應當具備使用這些平臺的軟件開發經驗; 通過需求功能與設計模塊之間的列表對應,檢查每個需求功能是否都有相應的模塊來實現,保證需求功能的可追溯性和需求實現(模塊)的完整性,同時可以檢查重復和不必要的模塊。 在需求調研分析過程中對業務處理過程了解的完整性和準確性非常重要。調查了解清楚所有的業務流程才能設計出適合各流程業務節點用戶業務特點和習慣的軟件,使開發出來的軟件更受歡迎。當然在進行軟件概要設計時,要盡量排除業務流程的制約,即把流程中的各項業務結點工作作為獨立的對象,設計成獨立的模塊,充分考慮他們與其他各種業務對象模塊的接口,在流程之間通過業務對象模塊的相互調用實現各種業務,這樣,在業務流程發生有限的變化時(每個業務模塊本身的業務邏輯沒有變的情況下),就能夠比較方便地修改系統程序模塊間的調用關系而實現新的需求。如果這種調用關系被設計成存儲在配置庫的數據字典里,則連程序代碼都不用修改,只需修改數據字典里的模塊調用規則即可。 七、概要設計的重要輸出 編碼規范:信息形式、接口規約、命名規則; 物理模型:組件圖、配置圖; 不同角度的構架視圖:用例視圖、邏輯視圖、進程視圖、部署視圖、實施視圖、數據視圖(可選); 系統總體布局:哪些部分組成、各部分在物理上、邏輯上的相互關系; 兩個不可忽視的輸出: 與需求功能的關系:對于需求中的每一個功能,用哪一層、哪個模塊、哪個類、哪個對象來實現(一對多關系);反過來,應當說明將要創建的系統每一層、每個模塊、每個對象、每一個類“做什么”,他們是為了幫助實現哪些功能(一對多關系)。(需求的顆粒度在一開始往往是比較粗的,因此根據功能點對于整體項目規模的估計或得到項目WBS其誤差范圍也是比較大的。更為重要的原因是,需求往往不是編碼工作分解的準確依據,因為一個需求的功能點可能對應多個代碼模塊,而多個需求的功能點也可能只對應一個或少數代碼模塊,同時還有軟件復用等因素要考慮,因此只有在概要設計完成以后才能準確地得到詳細設計或編碼階段的二次WBS,并估計較為準確的整體項目規模。) 邏輯與物理位置:每個對象在邏輯上分別落在哪一層、哪個模塊、哪個類;在物理上每個模塊、每個對象、每一個類放在哪個應用服務器或客戶端的哪個目錄、哪個文件(庫),或者是建立在數據庫管理系統中的什么東東(過程、函數、視圖、觸發器等等)。 八、結構化與面向對象方法特點比較 1. 從概念方面看,結構化軟件是功能的集合,通過模塊以及模塊和模塊之間的分層調用關系實現;面向對象軟件是事物的集合,通過對象以及對象和對象之間的通訊聯系實現; 2. 從構成方面看,結構化軟件=過程+數據,以過程為中心;面向對象軟件=(數據+相應操作)的封裝,以數據為中心; 3. 從運行控制方面看,結構化軟件采用順序處理方式,由過程驅動控制;面向對象軟件采用交互式、并行處理方式,由消息驅動控制; 4. 從開發方面看,結構化方法的工作重點是設計;面向對象方法的工作重點是分析;但是,在結構化方法中,分析階段和設計階段采用了不相吻合的表達方式,需要把在分析階段采用的具有網絡特征的數據流圖轉換為設計階段采用的具有分層特征的結構圖,在面向對象方法中則不存在這一問題。 5. 從應用方面看,相對而言,結構化方法更加適合數據類型比較簡單的數值計算和數據統計管理軟件的開發;面向對象方法更加適合大型復雜的人機交互式軟件和數據統計管理軟件的開發; 參考文獻: 《實用軟件工程》第二版,鄭人杰、殷人昆、陶永雷等著 《微軟項目:求生法則》Steve McConnell著,余孟學譯 《軟件工程:實踐者的研究方法》(第5版)Roger S.Pressman著 《軟件構架實踐》SEI軟件工程譯叢,林·巴斯著 《RUP2000》電子版; 《UML與系統分析設計》張龍祥著; 《面向對象的分析與設計》楊正甫著;
Oracle開發人員 JAVA存儲過程 利用Java存儲過程簡化數據庫操作 作者:Kuassi Mensah 利用Java存儲過程溝通SQL、XML、Java、J2EE和Web服務。 存儲過程(stored procedure)允許將運行于數據庫層中的持久性邏輯與運行于中間層中的商務邏輯有效地分離開來。這種分離可以降低整個應用程序的復雜性,并提供其重用性、安全性、性能和可伸縮性。
但是,妨礙存儲過程廣泛采用的一個主要障礙是不同數據庫廠商使用各種專有的、且依賴于數據庫的實現語言。使用基于Java的存儲過程可以解決這一問題。Oracle已經實現了ANSI標準,這些標準規定了從SQL中將靜態Java方法作為過程或函數進行調用的能力。這種實現被簡單地稱作"Java存儲過程"。
在本文中,你將了解基于Java的存儲過程如何幫助簡化商務邏輯、提高其性能,并擴展數據庫的功能。本文將介紹Oracle如何在數據庫內啟用基于Java的存儲過程。還會介紹Java存儲過程如何訪問數據,以及如何創建基本Java存儲過程。
選擇PL/SQL還是Java
在考慮Oracle存儲過程時,你可能會想到PL/SQL。不過,從Oracle8i開始,Oracle已經在數據庫中支持Java,從而為存儲過程提供了不同于PL/SQL的開放式和可移植的方法。我可以聽到"$64 000問題":"我如何在PL/SQL和Java之間做出選擇?我是否應當忘記已經學習的所有PL/SQL相關知識,而變為一個Java天地的新手?"
兩種語言都適用于數據庫編程,都有自己的優點和弱點。在決定選擇哪一種語言時,可以參考下面根據經驗得出的通用規則:
對于要求與SQL進行無縫集成的數據庫中心來說則邏輯使用PL/SQL,從而完成對數據庫對象、類型和特性的訪問。 出于與數據庫的無關性考慮時,可以選擇Java作為開放式的語言來取代PL/SQL,同時也為了集成和溝通SQL、XML、J2EE和Web服務等各個領域。 OralceJVM使得Java可以運行在數據庫中
從Oracle8i版本1(Oralce8.1.5)開始,Oracle便提供緊密集成的Java虛擬機(JVM),JVM支持Oralce的數據庫會話期結構。任何數據庫對話期都可以在第一Java代碼調用時啟動一個虛擬上專用的JVM,后續的用戶可以使用這一已經存在的支持Java的會話期。事實上,所有會話共享同一JVM代碼并保持"僅靜態"的私有狀態,而垃圾則收集在單個對話期空間內,從而為各個Java對話期提供了和SQL操作相同的對話期隔離和數據完整性能力。這里,不需要為了數據完整性而進行單獨的Java支持的過程。這一基于對話期的結構提供了較小的內存占用率,并使OracleJVM具有與Oracle數據庫一樣的線性SMP可伸縮性。
創建Java存儲過程
要將Java方法轉換為Java存儲過程需要幾個步驟,包括:用loadjava實用程序將Java類加載到數據庫中,利用調用規范(Call Spec)發布Java方法,將Java方法、參數類型和返回類型映射到其SQL的對應部分。下面部分說明如何完成這些步驟。
我將使用一個簡單的Hello類,它有一個方法Hello.world(),返回字符串"Hello world": public class Hello { public static String world () { return "Hello world"; } } Loadjava 實用程序
Loadjava是加載Java源文件、Java類文件和Java資源文件的實用程序,它可以用來驗證字節碼,并將Java類和JAR文件布置到數據庫中。它既可以通過命令行調用,也可以通過包含于DBMS_JAVA類中的loadjava()方法調用。為了加載我們的Hello.class示例,輸入: loadjava -user scott/tiger Hello.class
從Oracle9i版本2開始,loadjava允許通過為包含在被處理的類中的方法創建相應的Call Specs來自動將Java類發布為存儲過程。Oracle為開發、測試、調試和布置Java存儲過程提供了Oracle9i JDeveloper。
The Resolver Spec
基于JDK的JVM在列于CLASSPATH中的目錄中查找類引用,并對其進行解析。因為Oracle數據庫類存在于數據庫模式中,所以OracleJVM利用數據庫解析器(resolver)通過列于Resolver Spec中的模式查找并解析類引用。與CLASSPATH不同(CLASSPATH可以應用于所有的類),Resover Spec根據每類的情況進行應用。缺省解析器首先在加載類的模式中搜尋類,然后在公共同義詞(public synonyms)中搜索。 loadjava -resolve <myclass> 你可能需要指定不同的解析器,也可以在使用loadjava時強制進行解析,從而在布置時確定可能在以后運行時發生的任何問題。 loadjava -resolve -resolver "((* SCOTT) (foo/bar/* OTHERS) (* PUBLIC))" Call Spec和存儲過程調用
為了從SQL中調用Java方法(以及從PL/SQl和JDBC中調用),必須首先通過Call Spec發布公共靜態方法,它為SQL定義方法采用的參數以及返回的SQL類型。
在我們的例子中,我們將利用SQL*Plus連接到數據庫,并為Hello.world()定義一個頂級Call Spec: SQL> connect scott/tiger SQL> create or replace function helloworld return VARCHAR2 as language java name 'Hello.world () return java.lang.String'; / Function created. 可以像下面這樣調用Java存儲過程: SQL> variable myString varchar2[20]; SQL> call helloworld() into :myString; Call completed. SQL> print myString; MYSTRING --------------------- Hello world Java存儲過程可以通過其Call Spec從以下各項中進行調用:SQL DML語句(INSERT, UPDATE、DELETE、SELECT、CALL、EXPLAIN PLAN、LOCK TABLE和MERGE)、PL/SQL塊、子程序、程序包以及數據庫觸發器。Call Spec的美妙之處在于存儲過程實現可以從PL/SQL轉換為Java,反之亦可,這一點對于請求者是透明的。
Call Spec從實現語言中(PL/SQL或Java)中抽象出調用界面,因而使之能夠在原有應用程序和新的基于Java/J2EE的應用程序之間共享商務邏輯。但是,在從Java客戶程序調用在數據庫駐留的Java類時,你可能不希望通過PL/SQL包裝器(wrapper)。在以后的版本中,Oracle計劃提供一種機制,它可以使開發人員略過Call Spec。
高級數據訪問控制
Java存儲過程可用于控制和限制對Oracle數據的訪問,其方法是只允許用戶通過存儲過程管理數據,而存儲過程在其調用者的權限內執行,而不能對表本身進行訪問。例如,你可以在特定時間內禁止更新數據,或者使管理者只具有查詢工資數據的權利,而不能進行更新,或者記錄所有的訪問并通知某一安全機構。
原有應用程序與J2EE應用程序之間的數據邏輯共享因為原有應用程序與J2EE應用程序都通過Call Spec調用存儲過程,所以J2EE和非J2EE應用程序可以共享相同的數據邏輯。由于有了Call Spec,所以不用考慮所用的是何種實現語言(無論是PL/SQL還是Java),該數據邏輯都可以共享。
為BMP實體Bean自動生成主關鍵字
在對EJB實體bean應用BMP時,一個bean實例可以由自動生成的與新插入的數據相關聯的主關鍵字惟一確定,它是ejbCreate()的返回值。可以利用一個插入相應數據的存儲過程在一個數據庫操作中檢索ejbCeater()中的該值,并檢索或計算主關鍵字。作為另一種方法,也可以利用JDBC3.0的RETURN_GENERATED_KEYS特性,以一個SQL語句插入該數據并檢索相應的關鍵字(或ROWID)。但是,存儲過程方法在各個JDBC驅動器版本和數據庫之間更具可移植性。
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration> <session-factory>
<!-- properties -->
<property name="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:jtds:sqlserver://192.168.0.29:1433/HisenseCommunity</property> <property name="hibernate.connection.username">sa</property> <property name="hibernate.connection.password">admin</property> <property name="hibernate.dialect">org.hibernate.dialect.SybaseDialect</property> <property name="hibernate.connection.pool.size">20</property> <property name="hibernate.show_sql">true</property>
<!-- mapping files --> <mapping resource="hisense/ORMFILE/AdminInfoBean.hbm.xml"/> <mapping resource="hisense/ORMFILE/AdminLevel.hbm.xml"/> <mapping resource="hisense/ORMFILE/Operate.hbm.xml"/> <mapping resource="hisense/ORMFILE/Relation.hbm.xml"/> <mapping resource="hisense/ORMFILE/Community.hbm.xml"/> <mapping resource="hisense/ORMFILE/Category.hbm.xml"/> <mapping resource="hisense/ORMFILE/CategoryType.hbm.xml"/> <mapping resource="hisense/ORMFILE/AdBusiness.hbm.xml"/> <mapping resource="hisense/ORMFILE/AdClient.hbm.xml"/> <mapping resource="hisense/ORMFILE/AdContent.hbm.xml"/> <mapping resource="hisense/ORMFILE/AdType.hbm.xml"/> <mapping resource="hisense/ORMFILE/Profile.hbm.xml"/> <mapping resource="hisense/ORMFILE/ProfileDv.hbm.xml"/> <mapping resource="hisense/ORMFILE/ProfileAlbum.hbm.xml"/> <mapping resource="hisense/ORMFILE/Club.hbm.xml"/> <mapping resource="hisense/ORMFILE/CommendType.hbm.xml"/> <mapping resource="hisense/ORMFILE/Comment.hbm.xml"/> <mapping resource="hisense/ORMFILE/Goods.hbm.xml"/> <mapping resource="hisense/ORMFILE/CommunityMarket.hbm.xml"/> <mapping resource="hisense/ORMFILE/CommunityMarketType.hbm.xml"/> <mapping resource="hisense/ORMFILE/News.hbm.xml"/> <mapping resource="hisense/ORMFILE/Merchant.hbm.xml"/> <mapping resource="hisense/ORMFILE/Commend.hbm.xml"/> <mapping resource="hisense/ORMFILE/ClubActivities.hbm.xml"/> <mapping resource="hisense/ORMFILE/ActivityType.hbm.xml"/> <mapping resource="hisense/ORMFILE/EstateManagement.hbm.xml"/> <mapping resource="hisense/ORMFILE/ProfileAndClubRelations.hbm.xml"/> </session-factory> </hibernate-configuration>
這是我曾經為系統生成hbm文件時編寫的一個ant 的build.xml配置文件,這里面主要有兩類參數設置,一類是路徑設置,另一類是功能加載設置;下面通過看看我的注釋你就應該明白了: <?xml version="1.0" encoding="UTF-8"?> //xml標頭信息 <project name="Test" default="all" basedir="."> //basedir是指定根目錄,"."提當前目錄; <property name="classes" location="./classes"/> //生成類的指定目錄 <property name="src" value="src" /> //源文件,要編譯的源的目錄; <property name="db" value="db" /> //數據庫設置 <property name="lib" value="./aiihome_admin/WEB-INF/lib" /> //指定庫路徑; <property name="lib-xdoc" value="./lib" /> //指定xdoc庫路徑; <property name="build" value="classes" /> //成生輸出的目錄;
<path id="myclasspath"> //設置路徑組 <fileset dir="${lib}"> <include name="*.jar"/> </fileset> <fileset dir="${lib-xdoc}"> <include name="*.jar"/> </fileset>
</path>
<target name="init"> //設置初始化功能 <mkdir dir="${classes}"/> </target>
<target name="compile" depends="init"> //設置要完成的工作,depends指他的依賴項,也是必須項 <javac executable="jikes" classpathref="myclasspath" srcdir="${src}" destdir="${classes}"/> </target>
<target name="clean"> //設置清除功能 <delete dir="${classes}"/> //dir要清除的目錄 </target>
<target name="xdoc" description="Generates Hibernate class descriptor files."> //設置xdoc工作功能 <taskdef name="hibernatedoclet" classpathref="myclasspath" classname="xdoclet.modules.hibernate.HibernateDocletTask"> //任務名hibernatedoclet,類庫classname </taskdef> <hibernatedoclet destdir="${classes}"> //hibernatedoclet任務設置項 <fileset dir="${src}"> //源目錄 <include name="**/*.java"/> //文件名 </fileset> <hibernate version="2.0"/> //hibernate vs </hibernatedoclet> </target>
<target name="all" depends="xdoc" /> //執行任務名 <!-- Other target omited --> </project>
關于ant編譯文件的標簽很多,不同的標簽可以實現不同的功能,在編譯這一塊地,ant真是太強了,可惜我只知道皮毛,提供大家一個配置文件參考:在middlegen2里面有一個example里有一個生成ejb項目的build文件,它的生成項目比較全,應該可以滿足一般需要了。
用XDoclet生成hbm.xml就是在.java文件里寫入一些元數據,XDoclet會從這些數據以及類本身得到足夠的信息來生成目標文件。當然,除了用于hibernate,XDoclet還可以用于web、ejb等等很多用途。
XDoclet要從sourceforge上下載,包含了很多jar包、文檔和例子,我覺得文檔做得還是不錯的,查起來比較方便。要使用XDoclet,一般要通過ant來完成,也就是在ant腳本里加入XDoclet的內容。
由于eclipse已經包含了ant支持,因此我沒有專門去下載一個ant回來,而是直接使用eclipse帶的,版本是1.5.3。
創建一個名為build.xml的腳本(其實應該換個名,比如gen-hbm.xml,看起來比較明白),內容如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="XDoclet Examples" default="hibernate" basedir="."> <property name="xdoclet.root.dir" value="c:/xdoclet-1.2.1"/> <property name="xdoclet.lib.dir" value="${xdoclet.root.dir}/lib"/> <path id="myclasspath"> <fileset dir="${xdoclet.lib.dir}"> <include name="*.jar"/> </fileset> </path> <taskdef name="hibernatedoclet" classname="xdoclet.modules.hibernate.HibernateDocletTask" classpathref="myclasspath" /> <target name="hibernate" description="Generate mapping documents">
<echo>+---------------------------------------------------+</echo> <echo>| |</echo> <echo>| R U N N I N G H I B E R N A T E D O C L E T |</echo> <echo>| |</echo> <echo>+---------------------------------------------------+</echo>
<hibernatedoclet destdir="./src" excludedtags="@version,@author,@todo,@see" addedtags="@xdoclet-generated at ${TODAY},@copyright The XDoclet Team,@author XDoclet,@version ${version}" force="false" verbose="true">
<fileset dir="./src"> <include name="org/haree/struts/form/UserForm.java"/> </fileset>
<hibernate version="2.0"/>
</hibernatedoclet> </target> </project>
我曾經卡住的一個地方就是在taskdef里的classpathref屬性。一開始我在eclipse的ant運行參數里設置了XDoclet相關的包,總是提示:
Can't create a hibernate element under hibernatedoclet. Make sure the jar file containing the corresponding subtask class is on the classpath specified in the <taskdef> that defined {2}.
后來如上設置了classpathref,即包含了XDoclet使用到的包,并將eclipse的ant里關于XDoclet的包都去掉,竟然就成功了。其實現在也不明白為什么會這樣。。。
|