1. Torque介紹
Torque是一個持久層框架,也是jakarta的一個子項目,原來包括在Turbine框架中,從Turbine2.2開始Torque被分離出來作為一個單獨的子項目。目前最高版本是3.3。
2. 對持久層以及持久層框架的理解
所謂持久層就是在整個系統(tǒng)中與持久存儲介質如Database,LDAP Server,XML等打交道的部分。持久層框架的作用就是使持久層訪問持久介質更加方便。如果是為了訪問Database而建立的持久層框架那么就又有一個O/R Mapping的概念。O/R Mapping就是建立對象(Object)與關系數(shù)據(jù)庫(R)中的表(不一定是一對一)的映射。Torque就是這樣一種起到O/R Mapping作用的持久層框架。他使java程序員可以方便地通過操作普通java對象的方式來訪問數(shù)據(jù)庫,甚至不用了解數(shù)據(jù)庫的相關知識(最好是了解),另一個好處是屏蔽數(shù)據(jù)庫類型即可任意更換持久層框架支持的Database。
3. Torque的工作原理
一般在利用O/R Mapping框架進行開發(fā)的時候,有三個基本的單元即關系數(shù)據(jù)庫中的表(Table),Java中的持久對象(PO),定義PO到Table映射的xml文件(Schema)。
首先,Torque包含一個generator用來根據(jù)由開發(fā)者配置好的Schema來自動生成PO和Table,這就意味著開發(fā)者只要定義好Schema,PO和Table就可以自動生成了。
在生成好的PO和Table以后,開發(fā)者就可以利用PO來進行對Table的訪問了。為了達到這個目的Torque提供了一個運行時環(huán)境來保證代碼的正確運行。在工程中引入了torque相關的.jar就可以擁有這個運行環(huán)境了。
4. Torque中的包,類和接口
Torque的源碼提供的是運行環(huán)境,基于Torque開發(fā)關心的是生成的PO的使用方法即怎樣使用生成的PO來操作Table。下面會通過Torque導學上帶的例子來詳細說明。
5. 導學中的例子
5.1利用generator生成PO和Table
首先,要通過generator來生成PO和Table要定義Schema和進行generator的配置。
Schema的定義如下:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE database SYSTEM
"http://db.apache.org/torque/dtd/database_3_1.dtd">
<database
name="torque"
defaultIdMethod="idbroker">
<table name="book" description="Book Table">
<column
name="book_id"
required="true"
primaryKey="true"
type="INTEGER"
description="Book Id"/>
<column
name="title"
required="true"
type="VARCHAR"
size="255"
description="Book Title"/>
<column
name="isbn"
required="true"
type="VARCHAR"
size="24"
javaName="ISBN"
description="ISBN Number"/>
<column
name="publisher_id"
required="true"
type="INTEGER"
description="Foreign Key Publisher"/>
<column
name="author_id"
required="true"
type="INTEGER"
description="Foreign Key Author"/>
<foreign-key foreignTable="publisher" onDelete="cascade">
<reference
local="publisher_id"
foreign="publisher_id"/>
</foreign-key>
<foreign-key foreignTable="author" onDelete="cascade">
<reference
local="author_id"
foreign="author_id"/>
</foreign-key>
</table>
<table name="publisher" description="Publisher Table">
<column
name="publisher_id"
required="true"
primaryKey="true"
type="INTEGER"
description="Publisher Id"/>
<column
name="name"
required="true"
type="VARCHAR"
size="128"
description="Publisher Name"/>
</table>
<table name="author" description="Author Table">
<column
name="author_id"
required="true"
primaryKey="true"
type="INTEGER"
description="Author Id"/>
<column
name="first_name"
required="true"
type="VARCHAR"
size="128"
description="First Name"/>
<column
name="last_name"
required="true"
type="VARCHAR"
size="128"
description="Last Name"/>
</table>
</database>
在這個schema里定義了Table的結構,生成的PO在會按照一定規(guī)則與Table進行對應。
然后修改build.properties文件加入如下部分:
torque.database = mysql
torque.project = torque
torque.addGetByNameMethod = true
torque.addIntakeRetrievable = false
torque.addSaveMethod = true
torque.addTimeStamp = true
torque.basePrefix = Base
torque.complexObjectModel = true
torque.useClasspath = false
torque.useManagers = false
torque.targetPackage=org.together.om
torque.database.createUrl = jdbc:mysql://127.0.0.1/mysql
torque.database.buildUrl = jdbc:mysql://127.0.0.1/torque
torque.database.url = jdbc:mysql://127.0.0.1/torque
torque.database.driver = org.gjt.mm.mysql.Driver
torque.database.user = root
torque.database.password = haohao
torque.database.host = 127.0.0.1
torque.sameJavaName = false
關鍵是綠色標記的部分,表明是連接的mysql數(shù)據(jù)庫,并將生成的PO放到org.together.om包中。 最后利用ant執(zhí)行generator,這樣就可以在數(shù)據(jù)庫中生成相應的Table,并生成于Table對應的PO(放在定義好的org.together.om下)。拿schema中定義的Author為例,運行generator后可以在mysql數(shù)據(jù)庫中生成一張Author表,DDL如下:
CREATE TABLE `author` (
`author_id` int(11) NOT NULL default '0',
`first_name` varchar(128) NOT NULL default '',
`last_name` varchar(128) NOT NULL default '',
PRIMARY KEY (`author_id`)
) TYPE=MyISAM
在org.together.om包下會有一個BaseAuthor類(由于生成的PO比較多在下面會詳細介紹),這個類中會有如下的屬性與Table中的字段進行對應。
/** The value for the authorId field */
private int authorId;
/** The value for the firstName field */
private String firstName;
/** The value for the lastName field */
private String lastName;
5.2 由generator生成的PO的結構
在org.together.om下有若干類和一個子包map。map包下的也是運行環(huán)境相關的不用考慮。在org.together.om下會為schema中定義的每一個表生成四個相關的類。拿Book來說,有四個類和他對應,分別為:BaseAuthorPeer, AuthorPeer,BaseAuthor, Author。BaseAuthorPeer和BaseAuthor分別是AuthorPeer和Author的基類,在基類里是由generator生成的代碼,注意不要修改基類的代碼,因為每次利用generator生成時都會覆蓋基類的代碼(AuthorPeer和Author類不會被覆蓋)。
5.3 PO的使用方法
BaseAuthorPeer和BaseAuthor這兩個基類是用來提供底層功能的,我們只要操作AuthorPeer和Author類就可以完成對數(shù)據(jù)庫中的表author的操作如增加,刪除,更新和查詢等。
對author進行增加操作的代碼如下:
Author na = new Author();
na.setFirstName("a");
na.setLastName("b");
na.save(); // 或用AuthorPeer的靜態(tài)方法替代AuthorPeer.doInsert(na);
對author進行更新操作的代碼如下:
na.setLastName("c");
na.save(); //或用AuthorPeer的靜態(tài)方法替代AuthorPeer.doUpdate(na);
對author進行刪除操作的代碼如下:
AuthorPeer.doDelete(na); //進行delete時只能使用AuthorPeer的靜態(tài)方法
對author進行查詢,查詢出author表中的author_id字段的值在1和10000之間的所有數(shù)據(jù)
Criteria testCriteria = new Criteria();
testCriteria.add(AuthorPeer.AUTHOR_ID,1,Criteria.GREATER_THAN); testCriteria.add(AuthorPeer.AUTHOR_ID,10000,Criteria.LESS_THAN);
List tList = AuthorPeer.doSelect(testCriteria);
log.debug("all size:" + tList.size());
for (int i = 0; i < tList.size(); i++) {
Author o = (Author) tList.get(i);
System.out.println("Author" + i + " : " + o.toString());
}
以上介紹了PO的基本用法,在實際的應用中往往比上述要復雜的多,但是掌握了基本的方法,其他的用法就可以在實際使用時查看手冊即可。Torque的doc上附帶的Toturial上面有使用generator的詳細說明和怎樣使用Torque進行開發(fā)的例子。
6. Torque在ACI中的應用
看了一下ACI的源碼,torque自動生成的部分沒有任何改動,即都是直接使用生成的PO。但在TorqueACIStorage.java中關于Torque的用法要比上述的例子中多了一個事務處理情況,以下給出使用Torque進行事務處理的例子。
//創(chuàng)建JDBC連接用于控制事務
java.sql.Connection conn = null;
try{
//開始事務
conn=Transaction.begin(BaseAuthorPeer.getMapBuilder().getDatabaseMap().getName());
Author ta = new Author();
ta.setFirstName("t");
ta.setLastName("t");
AuthorPeer.doInsert(ta,conn);
//String ab = null; //人為制造異常使事務回滾
//ab.toLowerCase();
Publisher tp = new Publisher();
tp.setName("t");
PublisherPeer.doInsert(tp,conn);
//提交事務,會自動釋放連接
Transaction.commit(conn);
} catch (Exception ex) {
//回滾事務
Transaction.safeRollback(conn);
log.error(ex);
}
ACI中也有一些復雜一點的查詢條件(Criteria)的構造,在Torque的docs中的criteria-howto.html文件中都應該能夠找到。