DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> castor概述
castor概述
編輯:XML詳解     

Castor是ExoLab Group下面的一個開放源代碼的項目,它主要實現的是O/R映射功能。它主要API和數據接口為:JDO-like, SQL, OQL, JDBC, LDAP, XML, DSML。它支持分布式目錄事務處理和時間;提供處理XML、Directory、XADirectory的類庫,提供從XML到Java類的轉換機制。

  上面這段是網上的一段評論,大概介紹了Castor的一些特性,我們需要注意的是,Castor所提供的是Castor JDO,而不是SUN所提供的JDO規范(JSR000012),所以在上面的評論中使用了JDO-like這樣的評語,在後面我們會進一步討論這個問題的。

  呵呵,不過在我看來,Castor對我們的意義,最重要的就是其XML映射機制和其獨創的Castor JDO的機制了。下面我會分別就這兩個問題加以介紹:

  一、Castor XML

  我們可以認為這是一個獨立的Framework,專門負責與XML打交道。在了解眾多的類和API之前,我們有必要了解其整體的構建思想。在OOP中,我們都知道,對象是類的實體化,我們也知道,在OP中所要完成的工作是將對象持久保存下來,那麼相對的,我們同樣可以用類似的方法將類的定義和信息也保存下來,這是否可以稱為CP呢?呵呵,不管叫什麼名字,在Castor中的XML處理中,就是根據這樣的思想完成了兩個獨立的功能塊,一塊負責類到XML的保存和加載,另一塊負責對象到XML的保存和加載。具體的構造我們可以參看下圖:

castor概述

  如上圖所描述的,marshaller和unmarshaller負責對象和XML文件間的轉換。這種轉換過程主要在服務器端完成。在運行中,客戶端的請求發送到服務器端後,對內存中的對象進行相應操作,然後將處理完畢的對象marshall成為XML文件,或者進一步將XML文件格式化為Html文件發送到客戶端。如果以XML文件格式發送到客戶端,那麼在客戶端實行unmarshall操作將XML文件還原為內存中的對象,這樣就完成了交互過程。

castor概述

  至於source generator則和TOPLINK中實現的相類似,不過它沒有提供可視化的XML Schema的工具而已。我們編寫好描述類結構的XML文件,然後運行Castor提供的source generator就可以自動生成Java代碼了。有趣的是,它自動生成的代碼和BEAN的風格很類似,很容易看懂。

  對於XML而言,只要把握了這樣的整體,其他的諸如代碼生成中的兩種模式、映射規范、數據結構問題等細節問題就很簡單了,在文檔中附有很實用的例子和解釋,這裡就不再多說了。

  二、Castor JDO

  要了解JDO首先要認識兩個基本的問題:

  1、和SUN JDO的關系

  Castor JDO和SUN JDO並不相同,Castor JDO是獨立於SUN JDO發展起來的,但是它們所完成的工作非常相似。雖然也可以將Castor JDO重新定制成SUN JDO那個樣子,但是由於兩者在鎖定策略上存在的根本差異,這樣做並不劃算。在內部,Castor JDO為所有事務中的每個活動的持久性對象只維護一份鎖定(和緩存)的備份。而在SUN中則對每個事務中的每個持久性對象各維護一個備份,並且SUN JDO還需要字節碼編輯器,而CastorJDO並不需要。Castor還提供了其他的一些特性,比如說key generators,long transaction support 以及 OQL query,這些都在SUN的JSR中是看不到的。所以我們在前面對Castor的評價是JDO-LIKE的。

  2、和EJB的關系

  Castor和EJB很難說誰更好一些。

  一個實體Bean可以管理它自身的持久化。它要麼調用BMP(Bean Managed Persistence)來自己管理持久化,要麼就依靠它的容器的CMP(Container Managed Persistence)來做到持久化。


 

對於BMP來說,一個實體BEAN可以使用Castor JDO作為它的持久化機制,也可以使用其他的機制,比如說直接調用JDBC。

  對於CMP來說,一個EJB Container可以將它們的CMP基於Castor JDO來實現,那麼Castor JDO將被用來將實體BEAN持久化。如果開發者需要EJB的life-cycle管理, , "write once deploy anywhere" 和其他分布式應用程序的優點,那麼建議你直接使用EJB。否則,使用Castor將會更簡單,而且還開放源代碼,開銷更小,並提供更多的設計自由性,以及所提供的集成的XML支持。我們應當根據實際情況來選擇所使用的機制。

  具體的使用我就不知道怎麼說了,呵呵,下面把它的一個概括性介紹的文檔給翻譯了下來,Castor JDO的一些基本的使用特性裡面基本上都介紹或者提及了,比如說JDO的兩種使用環境的區別、OQL query、生存期問題、基本語義、與XML聯用等,如果需要更具體的情況請自行查詢Castor的文檔。

  <翻譯來自castor的聯機文檔--Castor JDO概況>

  打開一個JDO數據庫

  CatorJDO支持兩種類型的環境,客戶端應用程序和J2EE服務器。客戶端應用程序負責設置數據庫連接和管理事務處理。J2EE應用程序使用JNDI來獲取預先配置好的數據庫連接,並且使用UserTransaction或者CMT(container managed transaction)來管理事務。如果你在這兩種環境中用過JDBC,那麼你對它們之間的異同會很了解。

  客戶端應用程序

  客戶端應用程序負責設置數據庫連接和管理事務處理。數據庫的設置是通過一個與映射文件相連接的獨立的XML文件來實現的。在例子中就是database.XML,但是其實我們可以使用任何的名字。

  org.exolab.castor.jdo.JDO定義了數據庫的名字和屬性,並被用來打開一個數據庫連接。通過使用setConfiguration命令來指定配置文件URL,我們可以裝載數據庫的配置。使用同一個配置來創建多個JDO對象只會裝載配置文件一次。 org.exolab.castor.jdo.Database對象實現了到數據庫的開放連接。在定義裡,database對象不是thread safe因而不應該用於並發進程中。當開啟多個Database對象是會有一點開銷,並且JDBC連接is acquired only per open transaction。下面的代碼片顯示了在典型的客戶端應用程序中的打開一個數據庫,運行一個事務,然後關閉數據庫的過程。

 

JDO jdo;
Database db;
// 定義JDO對象
jdo = new JDO();
jdo.setDatabaseName( "mydb" );
jdo.setConfiguration( "database.XML" );
jdo.setClassLoader( getClass().getClassLoader() );
// 獲取一個新的數據庫
db = jdo.getDatabase();
// 開始事務處理
db.begin();
// 事務過程
. . .
// 提交事務,關閉數據庫
db.commit();
db.close();

  J2EE 程序( 不太懂,所以沒譯,大概說的是在J2EE中由於使用持久化方式的不通而產生的編碼不同的問題,可以參考一下我們前面對EJB持久化問題的探討)

  Note: We are now working on supporting Castor inside a J2EE container. Stay tuned for more information. J2EE applications depend on the J2EE container (Servlet, EJB, etc) to configure the database connection and use JNDI to look it up. This model allows the application deployer to configure the database propertIEs from a central place, and gives the J2EE container the ability to manage distributed transactions across multiple data sources. Instead of constructing a org.exolab.castor.jdo.JDO the application uses the JNDI namespace to look it up. We recommend enlisting the JDO object under the Java:comp/env/jdo namespace, compatible with the convention for listing JDBC resources.

  下面的代碼片使用JNDI來查找一個數據庫,並且使用UserTransaction來進行事務管理:

InitialContext ctx;
UserTransaction ut;
Database db;
// 在JNDI中查找數據庫
ctx = new InitialContext();
db = (Database) ctx.lookup( "Java:comp/env/jdo/mydb" );
// 開始事務處理
ut = (UserTransaction) ctx.lookup( "Java:comp/UserTransaction" );
ut.begin();
// 事務過程
. . .
// 提交事務,關閉數據庫
ut.commit();
db.close();
When the transaction is managed by the container, a common case with EJB beans and in particular entity beans, there is no need to being/commit the transaction explicitly. Instead the application server takes care of enlisting the database in the ongoing transaction and commiting/rollingback at the proper time.
The following code snippet relIEs on the container to manage the transaction:
InitialContext ctx;
UserTransaction ut;
Database db;
// Lookup databse in JNDI
ctx = new InitialContext();
db = (Database) ctx.lookup( "Java:comp/env/jdo/mydb" );
// Do something
. . .
// Close the database
db.close();


 

總結:開啟一個數據庫在客戶端和在服務器端是有區別的,主要體現在事務處理的過程、配置問題等上面,需要注意。

  使用JDO數據庫

  臨時對象和持久對象

  所有的JDO操作都發生在事務中。事務提交時,JDO將數據從數據庫中加載到內存中的對象中,讓應用程序對對象進行操作,然後再將對象的新狀態存儲到數據庫中。所有的對象可以是兩種狀態:臨時的或者持久的。

  臨時的:指當事務提交時狀態不會被保存的對象。對對象的修改不會表現在數據庫中。

  持久的:指當事務提交時狀態將被保存的對象。對對象的修改將反映在數據庫中。

  在下面情況下對象為持久的: 1、一個查詢的結果,

  2、使用create(java.lang.Object)或者update(Java.lang.Object)將它加入到數據庫中。

  所有不是持久性的對象就是臨時性對象,當事務提交或者回滾時,所有的持久性對象變成臨時對象。

  在客戶端程序中,使用begin(),commit()和rollback()來管理事務。在J2EE程序中,JDO依靠container來含蓄或明確(基於bean的transaction屬性值)的使用Javax.transaction.UserTransaction接口來管理事務。

  如果一個持久對象在事務中被改變了,在提交時修改會存入數據庫。如果事務回滾,數據庫不會被改變。如果要在兩個不同的事務中使用同一個對象,你必須重新查詢。

  對象的臨時和持久是從事務所屬的數據庫的角度來看的。一般來說持久對象只是對於一個數據庫而言,如果在另外一個數據庫中調用isPersistent(Java.lang.Object)將返回false。當然也可以讓一個持久對象對應於兩個數據庫,比如說在一個數據庫中運行查詢,而在另一個數據庫中創建它。

  OQLQuery

  OQL查詢被用來從數據庫中查詢和尋找對象。OQL查詢和SQL查詢類似,但是使用對象名稱而不是SQL名稱,並且不需要join子句。比如說,如果類型為TestObject的對象被加載了,OQL查詢將使用“FROM TestObject”,而不管到底表名為什麼。如果加載關聯的對象需要join,Castor將自動實現連接。

下面的代碼片使用OQL查詢來加載指定組中所有的對象。注意產品和組是關聯的對象,JDBC查詢使用了連接:

OQLQuery oql;
QueryResults results;
// Construct a new query and bind its parameters
oql = db.getOQLQuery( "SELECT p FROM Product p WHERE Group=$" );
oql.bind( groupId );
// RetrIEve results and print each one
results = oql.execute();
while ( results.hasMore() ) {
System.out.println( results.next() );
}

  下面的代碼片使用前面的查詢來獲得產品,將它們的價格減少25%,並且將它們存會數據庫(在這裡使用了客戶端程序事務):

while ( results.hasMore() ) {
Product prod;
prod = (Product) results.next();
prod.markDown( 0.25 );
prod.setOnSale( true );
}
// Explicitly commit transaction
db.commit();
db.close();

  如上面所描述的,查詢分三個步驟實現:一、使用OQL語法從數據庫中創建一個query對象;二、如果有參數,就將參數綁定到查詢中。參數綁定的順序和它們在OQL語法中出現的順序保持一致;三、執行查詢並獲得一系列為org.exolab.castor.jdo.QueryResults的對象。查詢創建一次後可以多次使用,不過每次都得重新綁定參數。查詢再次執行後,上一次的結果集可以繼續使用。參考下面的代碼來調用存儲過程:

  oql = db.getOQLQuery( "CALL sp_something($) AS myapp.Product" ); 在這裡sp_something是一個返回一個或多個結果集的存儲過程,字段順序和前面相同(對於沒有關聯的對象,順序為:標識符,接下來是所有其他的字段,順序和mapping.XML中定義的順序一致)。

Create/remove/update

  create(Java.lang.Object)方法在數據庫中創建一個新的對象,或者在JDO terminology中使得一個臨時對象持久化。如果事務被提交的話,這個使用create方法創建的對象將保持在數據庫中,否則將被刪除。如果使用數據庫中已經存在的標識來創建對象,將會產生一個異常。 下面的代碼片為先前查詢出來的一個組創建了一個新的產品:

Product prod;
// Create the Product object
prod = new Product();
prod.setSku( 5678 );
prod.setName( "Plastic Chair" );
prod.setPrice( 55.0 );
prod.setGroup( furnitures );
// Make is persistent
db.create( prod );

  remove(Java.lang.Object)方法產生相反的效果,它將刪除一個持久性對象。一旦刪除,任何事務都無法使用該對象。如果事務提交,這個對象將從數據庫中刪除,否則對象將仍然存在於數據庫中。如果試圖刪除一個非持久性對象,將產生異常。

  使用 JDO 和 XML

  CastorJDO和CastorXML結合起來,可以通過使用XML作為輸入和輸出來實現事務性數據庫操作。下面的程序片使用持久性和臨時性對象的結合來描述一個財務操作。

  這個例子獲取了兩個account對象並且從其中一個轉移了一筆金額到另外一個賬戶。轉移被描述為使用一個臨時對象(比如說無數據庫中的記錄),這個對象接下來被用於生成一個XML文檔來描述這次轉移過程。另外還有一個附加的過程(這裡沒有表現出來),是使用XSLT來將XML文檔轉換為一個Html頁面。

Transfer tran;
Account from;
Account to;
OQLQuery oql;
tran = new Transfer();
// Construct a query and load the two accounts
oql = db.getOQLQuery( "SELECT a FROM Account a WHERE Id=$" );
oql.bind( fromId );
from = oql.execute().nextElement();
oql.bind( toId );
to = oql.execute().nextElement();
// Move money from one account to the other
if ( from.getBalance() >= amount ) {
from.decBalance( amount );
to.incBalance( amount );
trans.setStatus( Transfer.COMPLETE );
trans.setAccount( from );
trans.setAmount( amount );
} else {
// Report an overdraft
trans.setStatus( Transfer.OVERDRAFT );
}
// Produce an XML describing the transfer
Marshaller.marshal( trans, outputStream );
The XML produced by the above code might look like:
Completed

  總結:在使用數據庫的過程中,我們需要區分好臨時對象和持久對象,並掌握靈活運用它們的方法,另外,Castor所支持的OQL的用法也值得研究,我們可以參考Castor所提供的詳細文檔進一步了解。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved