明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

Struts HOW-TO 系列 之 數(shù)據(jù)庫訪問

[摘要][訪問一個數(shù)據(jù)庫] 在一個其于Struts的應用系統(tǒng)的設計過程中,最好能在web/表示層(presentation layer)和你的商務邏輯類(包含所有數(shù)據(jù)訪問操作的層)的中間,定義一個Acti...
[訪問一個數(shù)據(jù)庫]

在一個其于Struts的應用系統(tǒng)的設計過程中,最好能在web/表示層(presentation layer)和你的商務邏輯類(包含所有數(shù)據(jù)訪問操作的層)的中間,定義一個Action類,作為小型的適配器(thin adapter)。

所以,你可以先定義一些商務API(business API),這些API就是簡單的Java類。你可以傳遞一些參數(shù)給這些對象,并從這些對象返回一個Java Bean或者Java Bean的集合。這個Action類負責調(diào)用這些對象,并把它們返回的值傳遞給web/表示層。

通常,你可以為每一個你需要調(diào)用的商務方法/商務類API創(chuàng)建一個Action類。理想情況下,所有的數(shù)據(jù)庫訪問代碼都被封裝進了這些商務API類里,所以Struts并不知道你正在使用的持久層(persistent layer)(甚至都不知道你使用了持久層)。它只需要傳遞一個主鍵(Key)或者一個查詢參數(shù),然后處理返回的結(jié)果bean或者bean集合。這樣,你就可以在其他的應用環(huán)境里復用這些商務API類,你還可以對這些獨立于Struts或HTTP環(huán)境的商務API進行單體測試。

開始的時候,最簡單的方法就是設計一個1:1的方案,為你的每一個商務API入口(entry-point)定義一個Action類。當你的經(jīng)驗豐富了以后,你也可以使用DispatchAction組合這些Action類。你甚至可以定義一個簡單的"框架"Action,用來調(diào)用所有的這些商務類。你可以在contrib目錄里找到Scaffold設計的ProcessAction,這是一個"框架"Action的完整實現(xiàn)。使用這種方案可以使用更少的Action類,但你必須對Struts和MVC框架的底層實現(xiàn)有較深的理解。不要害怕在開始的時候定義過多的Action,Struts的配置方案可以給予你充分的自由在以后重構(gòu)你的設計,因為你可以靈活的改變你的Action類,而不會對應用程序造成影響。

在理想情況下,商務邏輯層(business logic layer)應該封裝所有的數(shù)據(jù)訪問細節(jié),包括數(shù)據(jù)庫連接的獲得。但是,一些應用程序的設計要求調(diào)用者可以從一個DataSource對象來獲得數(shù)據(jù)庫連接。遇到這種情況時,Struts DataSource管理器可以使你在需要的時候配置這些DataSource資源。

Struts DataSource管理器在Struts配置文件(Struts-config.xml)里定義。這個管理器可以用來分發(fā)和配置任何實現(xiàn)了javax.sql.DataSource接口的數(shù)據(jù)庫連接池(connection pool)。如果你的DBMS或者容器內(nèi)置了符合這些要求的連接池,你可以優(yōu)先選用它。


[Jakarta的公共連接池實現(xiàn) - BasicDataSource]

如果你的手頭沒有連接池的本地(native)實現(xiàn),你可以使用Jakarta提供的公共連接池實現(xiàn)[org.apache.commons.dbcp.BasicDataSource],它可以和DataSource管理器"合作"的很好。另外,Struts還在它的util包里包含了一個GenericDataSource類,這也是一個連接池實現(xiàn)。但是這只是一個非常簡單的實現(xiàn)方案,不推薦使用,因為它可能在Struts的以后版本中被BasicDataSource或其它的數(shù)據(jù)源實現(xiàn)替換掉。

下面是一段Struts-config.xml配置文件中的數(shù)據(jù)源配置(使用GenericDataSource數(shù)據(jù)源實現(xiàn)),你可以更改相應的設置以適合你自己的系統(tǒng)。


<!-- configuration for GenericDataSource wrapper -->
<data-sources>
<data-source>
<set-property
property="autoCommit"
value="false"/>
<set-property
property="description"
value="Example Data Source Configuration"/>
<set-property
property="driverClass"
value="org.postgresql.Driver"/>
<set-property
property="maxCount"
value="4"/>
<set-property
property="minCount"
value="2"/>
<set-property
property="password"
value="mypassword"/>
<set-property
property="url"
value="jdbc:postgresql://localhost/mydatabase"/>
<set-property
property="user"
value="myusername"/>
</data-source>
</data-sources>

使用BasicDataSource數(shù)據(jù)源實現(xiàn)的配置方案如下:

<data-sources>
<!-- configuration for commons BasicDataSource -->
<data-source type="org.apache.commons.dbcp.BasicDataSource">
<set-property
property="driverClassName"
value="org.postgresql.Driver" />
<set-property
property="url"
value="jdbc:postgresql://localhost/mydatabase" />
<set-property
property="username"
value="me" />
<set-property
property="password"
value="test" />
<set-property
property="maxActive"
value="10" />
<set-property
property="maxWait"
value="5000" />
<set-property
property="defaultAutoCommit"
value="false" />
<set-property
property="defaultReadOnly"
value="false" />
<set-property
property="validationQuery"
value="SELECT COUNT(*) FROM market" />
</data-source>
</data-sources>

注意,你可以在你的應用系統(tǒng)中定義不止一個數(shù)據(jù)源,你可以根據(jù)需要定義多個數(shù)據(jù)源,并為它們分別起一個邏輯名(logical name)。這樣做可以給你的應用系統(tǒng)提供更好的安全性和可測量性(scalability),你還可以定義一個專用于測試的數(shù)據(jù)源。

配置好DataSource以后,你就可以在你的應用系統(tǒng)中使用這些數(shù)據(jù)源了。下面這段代碼演示了怎樣在Action類的execute方法中通過這些數(shù)據(jù)源來生成數(shù)據(jù)庫連接。

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
DataSource dataSource;
Connection cnn;

try
{
dataSource = getDataSource(request);
cnn = dataSource.getConnection();
// 數(shù)據(jù)連接已經(jīng)建立了,你可以做你想做的事情了
}
catch (SQLException e)
{
getServlet().log("處理數(shù)據(jù)庫連接", e);
}
finally
{
// 在finally塊里包含這些代碼
// 用以保證連接最后會被關(guān)閉
try
{
cnn.close();
}
catch (SQLException e)
{
getServlet().log("關(guān)閉數(shù)據(jù)庫連接", e);
}
}
}

注意:如果你使用公共的BasicDataSource,你提供給pingQuery屬性的查詢語句(如果你設置了話)必須至少要能返回一行記錄。

例子:SELECT COUNT(*) FROM VALIDTABLE

你可以把VALIDTABLE替換成你的數(shù)據(jù)庫中包含的任何有效的表。

[使用多個數(shù)據(jù)源]

如果你需要在模塊(Module)中使用多于一個的數(shù)據(jù)源,你可以在配置文件的<data-source>元素里包含一個key屬性。

<data-source>
<data-source key="A" type="org.apache.commons.dbcp.BasicDataSource">
…屬性配置略, 同上…
</data-source>
<data-source key="B" type="org.apache.commons.dbcp.BasicDataSource">
…屬性配置略, 同上…
</data-source>
</data-source>

你代碼里,你可以通過這些key獲得不同的數(shù)據(jù)源。代碼如下:


try
{
dataSourceA = getDataSource(request, "A");
dataSourceB = getDataSource(request, "B");


你可以根據(jù)需要為每一個模塊設置多個數(shù)據(jù)源。但同一模塊里每個數(shù)據(jù)源的key屬性必須唯一,因為Struts模塊系統(tǒng)是以每一個模塊為單位管理命名空間的。

[更多的內(nèi)容請參考:]

http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg24621.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg24709.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg24626.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg24331.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg24102.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg23501.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg23455.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg23375.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg23321.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg23098.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg22713.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg21974.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg21026.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg19338.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg18323.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg14975.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg14914.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg14435.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg01562.html

轉(zhuǎn)換/數(shù)據(jù)傳遞(Transformation/Data Transfer)
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg24480.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg23623.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg10195.html
http://www.mail-archive.com/Struts-user@jakarta.apache.org/msg10205.html

[提供動態(tài)結(jié)果集(dynamic result set)]

大多數(shù)的數(shù)據(jù)庫查詢結(jié)果都會跟你的已經(jīng)使用的ActionForms一一對應,你只需要把你的查詢結(jié)果集合提交給相應的ActionForm就可以了。但有時候,結(jié)果集(ResultSet)里有些字段并不是ActionForm的屬性,或者更糟。

幸運的是,Struts的自定義標簽集并不關(guān)心你傳遞給他們的bean類型。你甚至可以直接輸出結(jié)果集。但是由于結(jié)果集會一直保持著與數(shù)據(jù)庫的連接,并且由于它們把所有的數(shù)據(jù)都直接傳遞給了JSP,使得頁面變得零亂不堪。那么我們該怎么做呢?

從Struts 1.1開始,你可以使用新增加的ResultSetDynaClass來把你的結(jié)果集轉(zhuǎn)換成一個DynaBeans的ArrayList。Struts自定義標簽集可以像一般的JavaBean一樣使用DynaBean的屬性。(關(guān)于DynaActionForm類更詳細的信息,請參考Struts用戶手冊)。

ResultSetDynaClass類已經(jīng)包含在于BeanUtils.jar包中,所以你現(xiàn)在所要做的,只需要拿出這個工具,實現(xiàn)自己的傳遞方案吧…………