日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Spring - Java/J2EE Application Framework 应用框架 第 10 章 使用JDBC进行数据访问

發(fā)布時(shí)間:2025/3/21 java 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring - Java/J2EE Application Framework 应用框架 第 10 章 使用JDBC进行数据访问 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第?10?章?使用JDBC進(jìn)行數(shù)據(jù)訪問

10.1.?簡(jiǎn)介

Spring提供的JDBC抽象框架由core,?datasource,object和?support四個(gè)不同的包組成。

就和它名字的暗示一樣,org.springframework.jdbc.core包里定義了提供核心功能的類。 其中有各種SQLExceptionTranslator和DataFieldMaxValueIncrementer的實(shí)現(xiàn)以及一個(gè)用于JdbcTemplate的DAO基礎(chǔ)類。

org.springframework.jdbc.datasource包里有一個(gè)用以簡(jiǎn)化數(shù)據(jù)源訪問的工具類, 以及各種數(shù)據(jù)源的簡(jiǎn)單實(shí)現(xiàn),以被用來在J2EE容器之外不經(jīng)修改地測(cè)試JDBC代碼。 這個(gè)工具類提供了從JNDI獲得連接和可能用到的關(guān)閉連接的靜態(tài)方法。 它支持綁定線程的連接,比如被用于DataSourceTransactionManager。

接著,org.springframework.jdbc.object包里是把關(guān)系數(shù)據(jù)庫(kù)的查詢, 更新和存儲(chǔ)過程封裝為線程安全并可重用對(duì)象的類。 這中方式模擬了JDO,盡管查詢返回的對(duì)象理所當(dāng)然的“脫離”了數(shù)據(jù)庫(kù)連接。 這個(gè)JDBC的高層抽象依賴于org.springframework.jdbc.core包中所實(shí)現(xiàn)的底層抽象。

最后在org.springframework.jdbc.support包中你可以找到?SQLException的轉(zhuǎn)換功能和一些工具類。

在JDBC調(diào)用中被拋出的異常會(huì)被轉(zhuǎn)換成在定義org.springframework.dao包中的異常。 這意味著使用Spring JDBC抽象層的代碼不需要實(shí)現(xiàn)JDBC或者RDBMS特定的錯(cuò)誤處理。 所有的轉(zhuǎn)換后的異常都是unchecked,它允許你捕捉那些你可以恢復(fù)的異常, 并將其余的異常傳遞給調(diào)用者。

10.2.?使用JDBC核心類控制基本的JDBC處理和錯(cuò)誤處理

10.2.1.?JdbcTemplate

這是在JDBC核心包中最重要的類。它簡(jiǎn)化了JDBC的使用, 因?yàn)樗幚砹速Y源的建立和釋放。 它幫助你避免一些常見的錯(cuò)誤,比如忘了總要關(guān)閉連接。它運(yùn)行核心的JDBC工作流, 如Statement的建立和執(zhí)行,而只需要應(yīng)用程序代碼提供SQL和提取結(jié)果。這個(gè)類執(zhí)行SQL查詢, 更新或者調(diào)用存儲(chǔ)過程,模擬結(jié)果集的迭代以及提取返回參數(shù)值。它還捕捉JDBC的異常并將它們轉(zhuǎn)換成?org.springframework.dao包中定義的通用的,能夠提供更多信息的異常體系。

使用這個(gè)類的代碼只需要根據(jù)明確定義的一組契約來實(shí)現(xiàn)回調(diào)接口。?PreparedStatementCreator回調(diào)接口創(chuàng)建一個(gè)由該類提供的連接所建立的PreparedStatement, 并提供SQL和任何必要的參數(shù)。CallableStatementCreateor實(shí)現(xiàn)同樣的處理, 只是它創(chuàng)建了CallableStatement。RowCallbackHandler接口從數(shù)據(jù)集的每一行中提取值。

這個(gè)類可以直接通過數(shù)據(jù)源的引用實(shí)例化,然后在服務(wù)中使用, 也可以在ApplicationContext中產(chǎn)生并作為bean的引用給服務(wù)使用。 注意:數(shù)據(jù)源應(yīng)當(dāng)總是作為一個(gè)bean在ApplicationContext中配置, 第一種情況它被直接傳遞給服務(wù),第二種情況給JdbcTemplate。 因?yàn)檫@個(gè)類把回調(diào)接口和SQLExceptionTranslator接口作為參數(shù)表示,所以沒有必要為它定義子類。 這個(gè)類執(zhí)行的所有SQL都會(huì)被記入日志。

10.2.2.?數(shù)據(jù)源

為了從數(shù)據(jù)庫(kù)獲得數(shù)據(jù),我們需要得到數(shù)據(jù)庫(kù)的連接。 Spring采用的方法是通過一個(gè)數(shù)據(jù)源。?數(shù)據(jù)源是JDBC規(guī)范的一部分,它可以被認(rèn)為是一個(gè)通用的連接工廠。 它允許容器或者框架將在應(yīng)用程序代碼中隱藏連接池和事務(wù)的管理操作。 開發(fā)者將不需要知道連接數(shù)據(jù)庫(kù)的任何細(xì)節(jié),那是設(shè)置數(shù)據(jù)源的管理員的責(zé)任。 雖然你很可能在開發(fā)或者測(cè)試的時(shí)候需要兼任兩種角色,但是你并不需要知道實(shí)際產(chǎn)品中的數(shù)據(jù)源是如何配置的。

使用Spring的JDBC層,你可以從JNDI得到一個(gè)數(shù)據(jù)源,也可以通過使用Spring發(fā)行版提供的實(shí)現(xiàn)自己配置它。 后者對(duì)于脫離Web容器的單元測(cè)試是十分便利的。 我們將在本節(jié)中使用DriverManagerDataSource實(shí)現(xiàn),當(dāng)然以后還會(huì)提到其他的一些的實(shí)現(xiàn)。DriverManagerDataSource和傳統(tǒng)的方式一樣獲取JDBC連接。 為了讓DriverManager可以裝載驅(qū)動(dòng)類,你必須指定JDBC驅(qū)動(dòng)完整的類名。 然后你必須提供相對(duì)于各種JDBC驅(qū)動(dòng)的不同的URL。你必須參考你所用的驅(qū)動(dòng)的文檔,以獲得需要使用的正確參數(shù)。 最后,你還必須提供用來連接數(shù)據(jù)庫(kù)的用戶名和密碼 下面這個(gè)例子說明如何配置DriverManagerDataSource:

DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( "org.hsqldb.jdbcDriver"); dataSource.setUrl( "jdbc:hsqldb:hsql://localhost:"); dataSource.setUsername( "sa"); dataSource.setPassword( "");

10.2.3.?SQLExceptionTranslator

SQLExceptionTranslator是一個(gè)需要實(shí)現(xiàn)的接口, 它被用來處理SQLException和我們的數(shù)據(jù)訪問異常org.springframework.dao.DataAccessException之間的轉(zhuǎn)換。

實(shí)現(xiàn)可以是通用的(比如使用JDBC的SQLState值),也可以為了更高的精確度特殊化 (比如使用Oracle的ErrorCode)。

SQLErrorCodeSQLExceptionTranslator?是SQLExceptionTranslator的實(shí)現(xiàn),它被默認(rèn)使用。比供應(yīng)商指定的SQLState更為精確。 ErrorCode的轉(zhuǎn)換是基于被保存在SQLErrorCodes型的JavaBean中的值。 這個(gè)類是由SQLErrorCodesFactory建立并填充的,就像它的名字說明的,SQLErrorCodesFactory是一個(gè)基于一個(gè)名為"sql-error-codes.xml"的配置文件的內(nèi)容建立SQLErrorCodes的工廠。 這個(gè)文件帶有供應(yīng)商的碼一起發(fā)布,并且是基于DatabaseMetaData信息中的DatabaseProductName,適合當(dāng)前數(shù)據(jù)庫(kù)的碼會(huì)被使用。

SQLErrorCodeSQLExceptionTranslator使用以下的匹配規(guī)則:

  • 使用子類實(shí)現(xiàn)的自定義轉(zhuǎn)換。要注意的是這個(gè)類本身就是一個(gè)具體類,并可以直接使用, 在這種情況下,將不使用這條規(guī)則。

  • 使用ErrorCode的匹配。在默認(rèn)情況下,ErrorCode是從SQLErrorCodesFactory得到的。 它從classpath中尋找ErrorCode,并把從數(shù)據(jù)庫(kù)metadata中得到的數(shù)據(jù)庫(kù)名字嵌入它們。

  • 如果以上規(guī)則都無法匹配,那么是用SQLStateSQLExceptionTranslator作為默認(rèn)轉(zhuǎn)換器。

SQLErrorCodeSQLExceptionTranslator可以使用以下的方式繼承:

public class MySQLErrorCodesTransalator extends SQLErrorCodeSQLExceptionTranslator {protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {if (sqlex.getErrorCode() == -12345)return new DeadlockLoserDataAccessException(task, sqlex);return null;} }

在這個(gè)例子中,只有特定的ErrorCode'-12345'被轉(zhuǎn)換了,其他的錯(cuò)誤被簡(jiǎn)單的返回, 由默認(rèn)的轉(zhuǎn)換實(shí)現(xiàn)來處理。要使用自定義轉(zhuǎn)換器時(shí),需要通過setExceptionTranslator?方法將它傳遞給JdbcTemplate,并且在所有需要使用自定義轉(zhuǎn)換器的數(shù)據(jù)訪問處理中使用這個(gè)JdbcTemplate?下面是一個(gè)如何使用自定義轉(zhuǎn)換器的例子:

// create a JdbcTemplate and set data source JdbcTemplate jt = new JdbcTemplate(); jt.setDataSource(dataSource); // create a custom translator and set the datasource for the default translation lookup MySQLErrorCodesTransalator tr = new MySQLErrorCodesTransalator(); tr.setDataSource(dataSource); jt.setExceptionTranslator(tr); // use the JdbcTemplate for this SqlUpdate SqlUpdate su = new SqlUpdate(); su.setJdbcTemplate(jt); su.setSql("update orders set shipping_charge = shipping_charge * 1.05"); su.compile(); su.update();

這個(gè)自定義的轉(zhuǎn)換器得到了一個(gè)數(shù)據(jù)源, 因?yàn)槲覀內(nèi)匀恍枰J(rèn)的轉(zhuǎn)換器在sql-error-codes.xml中查找ErrorCode。

10.2.4.?執(zhí)行Statement

要執(zhí)行一個(gè)SQL,幾乎不需要代碼。你所需要的全部?jī)H僅是一個(gè)數(shù)據(jù)源和一個(gè)JdbcTemplate。 一旦你得到了它們,你將可以使用JdbcTemplate提供的大量方便的方法。 下面是一個(gè)例子,它顯示了建立一張表的最小的但有完整功能的類。

import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate;public class ExecuteAStatement {private JdbcTemplate jt;private DataSource dataSource;public void doExecute() {jt = new JdbcTemplate(dataSource);jt.execute("create table mytable (id integer, name varchar(100))"); }public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;} }

10.2.5.?執(zhí)行查詢

除了execute方法,還有大量的查詢方法。其中的一些被用來執(zhí)行那些只返回單個(gè)值的查詢。 也許你需要得到合計(jì)或者某一行中的一個(gè)特定的值。如果是這種情況,你可以使用queryForInt,?queryForLong或者queryForObject。 后者將會(huì)把返回的JDBC類型轉(zhuǎn)換成參數(shù)中指定的Java類。如果類型轉(zhuǎn)換無效,那么將會(huì)拋出一個(gè)InvalidDataAccessApiUsageException。 下面的例子有兩個(gè)查詢方法,一個(gè)查詢得到int,另一個(gè)查詢得到String。

import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate;public class RunAQuery {private JdbcTemplate jt;private DataSource dataSource;public int getCount() {jt = new JdbcTemplate(dataSource);int count = jt.queryForInt("select count(*) from mytable");return count;}public String getName() {jt = new JdbcTemplate(dataSource);String name = (String) jt.queryForObject("select name from mytable", java.lang.String.class);return name;}public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;} }

除了得到單一結(jié)果的查詢方法之外,還有一些方法,可以得到一個(gè)包含查詢返回的數(shù)據(jù)的List。 其中最通用的一個(gè)方法是queryForList,它返回一個(gè)List, 其中每一項(xiàng)都是一個(gè)表示字段值的Map。 你用下面的代碼在上面的例子中增加一個(gè)方法來得到一個(gè)所有記錄行的List:

public List getList() {jt = new JdbcTemplate(dataSource);List rows = jt.queryForList("select * from mytable");return rows;}

返回的List會(huì)以下面的形式:?[{name=Bob, id=1}, {name=Mary, id=2}].

10.2.6.?更新數(shù)據(jù)庫(kù)

還有很多更新的方法可以供你使用。我將展示一個(gè)例子,說明通過某一個(gè)主鍵更新一個(gè)字段。 在這個(gè)例子里,我用了一個(gè)使用榜定參數(shù)的SQL Statement。大多數(shù)查詢和更新的方法都有這個(gè)功能。 參數(shù)值通過對(duì)象數(shù)組傳遞。

import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate;public class ExecuteAnUpdate {private JdbcTemplate jt;private DataSource dataSource;public void setName(int id, String name) {jt = new JdbcTemplate(dataSource);jt.update("update mytable set name = ? where id = ?", new Object[] {name, new Integer(id)});}public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;} }

10.3.?控制如何連接數(shù)據(jù)庫(kù)

10.3.1.?DataSourceUtils

這個(gè)輔助類提供從JNDI獲取連接和在必要時(shí)關(guān)閉連接的方法。它支持線程綁定的連接, 比如被用于DataSourceTransactionManager。

注意:方法getDataSourceFromJndi用以針對(duì)那些不使用BeanFactory或者ApplicationContext 的應(yīng)用。對(duì)于后者,建議在factory中配置你的bean甚至JdbcTemplate的引用: 使用JndiObjectFactoryBean可以從JNDI中得到一個(gè)DataSource?并將DataSource的引用給別的bean。要切換到另一個(gè)DataSource?就僅僅是一個(gè)配置的問題:你甚至可以用一個(gè)非JNDI的DataSource來替換?FactoryBean的定義!

10.3.2.?SmartDataSource

實(shí)現(xiàn)這個(gè)接口的類可以提供一個(gè)關(guān)系數(shù)據(jù)庫(kù)的連接。 它繼承javax.sql.DataSource接口,使用它可以知道在一次數(shù)據(jù)庫(kù)操作后, 是否需要關(guān)閉連接。如果我們需要重用一個(gè)連接,那么它對(duì)于效率是很有用的。

10.3.3.?AbstractDataSource

這個(gè)實(shí)現(xiàn)Spring的DataSource的抽象類,關(guān)注一些"無趣"的東西。 如果你要寫自己的DataSource實(shí)現(xiàn),你可以繼承這個(gè)類。

10.3.4.?SingleConnectionDataSource

這個(gè)SmartDataSource的實(shí)現(xiàn)封裝了單個(gè)在使用后不會(huì)關(guān)閉的連接。 所以很明顯,它沒有多線程的能力。

如果客戶端代碼想關(guān)閉這個(gè)認(rèn)為是池管理的連接,比如使用持久化工具的時(shí)候, 需要將suppressClose設(shè)置成true。這樣會(huì)返回一個(gè)禁止關(guān)閉的代理來接管物理連接。 需要注意的是,你將無法將不再能將這個(gè)連接轉(zhuǎn)換成本地Oracle連接或者類似的連接。

它的主要作用是用來測(cè)試。例如,它可以很容易的讓測(cè)試代碼脫離應(yīng)用服務(wù)器測(cè)試,而只需要一個(gè)簡(jiǎn)易的JNDI環(huán)境。 和DriverManagerDataSource相反,它在所有的時(shí)候都重用一個(gè)連接, 以此來避免建立物理連接過多的消耗。

10.3.5.?DriverManagerDataSource

這個(gè)SmartDataSource的實(shí)現(xiàn)通過bean的屬性配置JDBC驅(qū)動(dòng), 并每次都返回一個(gè)新的連接。

它對(duì)于測(cè)試或者脫離J2EE容器的獨(dú)立環(huán)境都是有用的, 它可以作為不同的ApplicationContext中的數(shù)據(jù)源bean, 也可以和簡(jiǎn)易的JNDI環(huán)境一起工作。被認(rèn)為是池管理的Connection.close()操作 的調(diào)用只會(huì)簡(jiǎn)單的關(guān)閉連接,所以任何使用數(shù)據(jù)源的持久化代碼都可以工作。

10.3.6.?DataSourceTransactionManager

這個(gè)PlatformTransactionManager的實(shí)現(xiàn)是對(duì)于單個(gè)JDBC數(shù)據(jù)源的。 從某個(gè)數(shù)據(jù)源綁定一個(gè)JDBC連接到一個(gè)線程,可能允許每個(gè)數(shù)據(jù)源一個(gè)線程連接。

應(yīng)用程序的代碼需要通過DataSourceUtils.getConnection(DataSource)取得JDBC連接代替 J2EE標(biāo)準(zhǔn)的方法DataSource.getConnection。這是推薦的方法, 因?yàn)樗鼤?huì)拋出org.springframework.dao中的unchecked的異常代替SQLException。 Framework中所有的類都使用這種方法,比如JdbcTemplate。 如果不使用事務(wù)管理,那么就會(huì)使用標(biāo)準(zhǔn)的方法,這樣他就可以在任何情況下使用。

支持自定義的隔離級(jí),以及應(yīng)用于適當(dāng)?shù)腏DBC statement查詢的超時(shí)。 要支持后者,應(yīng)用程序代碼必須使用JdbcTemplate或者對(duì)每一個(gè)創(chuàng)建的statement 都調(diào)用DataSourceUtils.applyTransactionTimeout。

因?yàn)樗恍枰萜髦С諮TA,在只有單個(gè)資源的情況下, 這個(gè)實(shí)現(xiàn)可以代替JtaTransactionManager。 如果你堅(jiān)持需要的連接的查找模式,兩者間的切換只需要更換配置。 不過需要注意JTA不支持隔離級(jí)。

10.4.?JDBC操作的Java對(duì)象化

org.springframework.jdbc.object包由一些允許你 以更面向?qū)ο蟮姆绞皆L問數(shù)據(jù)庫(kù)的類組成。你可以執(zhí)行查詢并獲得一個(gè)包含業(yè)務(wù)對(duì)象的List, 這些業(yè)務(wù)對(duì)象關(guān)系數(shù)據(jù)的字段值映射成它們的屬性。你也可以執(zhí)行存儲(chǔ)過程,更新,刪除和插入操作。

10.4.1.?SqlQuery

這是一個(gè)表示SQL查詢的可重用的而且線程安全的對(duì)象。 子類必須實(shí)現(xiàn)newResultReader()方法來提供一個(gè)對(duì)象,它能在循環(huán)處理ResultSet的時(shí)候保存結(jié)果。 這個(gè)類很少被直接使用,而使用它的子類MappingSqlQuery,它提供多得多的方法 將數(shù)據(jù)行映射到Java類。MappingSqlQueryWithParameters?和UpdatableSqlQuery是繼承SqlQuery的另外兩個(gè)實(shí)現(xiàn)。

10.4.2.?MappingSqlQuery

MappingSqlQuery是一個(gè)可以重用的查詢對(duì)象, 它的子類必須實(shí)現(xiàn)抽象方法mapRow(ResultSet, int)來把JDBC?ResultSet的每一行轉(zhuǎn)換成對(duì)象。

在所有的SqlQuery實(shí)現(xiàn)中,這個(gè)類是最常使用并且也是最容易使用的。

下面是一個(gè)自定義查詢的簡(jiǎn)單例子,它把customer表中的數(shù)據(jù)映射成叫做Customer的Java類。

private class CustomerMappingQuery extends MappingSqlQuery {public CustomerMappingQuery(DataSource ds) {super(ds, "SELECT id, name FROM customer WHERE id = ?");super.declareParameter(new SqlParameter("id", Types.INTEGER));compile();}public Object mapRow(ResultSet rs, int rowNumber) throws SQLException {Customer cust = new Customer();cust.setId((Integer) rs.getObject("id"));cust.setName(rs.getString("name"));return cust;} }

我們?yōu)閏ustomer查詢提供一個(gè)構(gòu)建方法,它只有數(shù)據(jù)源這一個(gè)參數(shù)。 在構(gòu)建方法中,我們調(diào)用超類的構(gòu)建方法,并將數(shù)據(jù)源和將要用來查詢?nèi)〉脭?shù)據(jù)的SQL作為參數(shù)。 因?yàn)檫@個(gè)SQL將被用來建立PreparedStatement,所以它可以包含?來綁定執(zhí)行時(shí)會(huì)得到的參數(shù)。 每一個(gè)參數(shù)必須通過declareParameter方法并傳遞給它一個(gè)SqlParameter來聲明。?SqlParameter有一個(gè)名字和一個(gè)在java.sql.Types定義的JDBC類型。 在所有的參數(shù)都定義完后,我們調(diào)用compile方法建立隨后會(huì)執(zhí)行的PreparedStatement。

我們來看一段代碼,來實(shí)例化這個(gè)自定義查詢對(duì)象并執(zhí)行:

public Customer getCustomer(Integer id) {CustomerMappingQuery custQry = new CustomerMappingQuery(dataSource); Object[] parms = new Object[1];parms[0] = id;List customers = custQry.execute(parms);if (customers.size() > 0)return (Customer) customers.get(0);elsereturn null;}

在例子中的這個(gè)方法通過一個(gè)參數(shù)id得到customer。在建立了CustomerMappingQuery?類的一個(gè)實(shí)例后,我們?cè)賱?chuàng)建一個(gè)數(shù)組,用來放置所有需要傳遞的參數(shù)。 在這個(gè)例子中只有一個(gè)Integer的參數(shù)需要傳遞。 現(xiàn)在我們使用這個(gè)數(shù)組執(zhí)行查詢,我們會(huì)得到一個(gè)List包含著Customer對(duì)象, 它對(duì)應(yīng)查詢返回結(jié)果的每一行。在這個(gè)例子中如果有匹配的話,只會(huì)有一個(gè)實(shí)體。

10.4.3.?SqlUpdate

這個(gè)RdbmsOperation子類表示一個(gè)SQL更新操作。就像查詢一樣, 更新對(duì)象是可重用的。和所有的RdbmsOperation對(duì)象一樣,更新可以有參數(shù)并定義在SQL中。

類似于查詢對(duì)象中的execute()方法,這個(gè)類提供很多update()的方法。

這個(gè)類是具體的。通過SQL設(shè)定和參數(shù)聲明,它可以很容易的參數(shù)化,雖然他也可以子例化 (例如增加自定義方法)。

import java.sql.Types;import javax.sql.DataSource;import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.object.SqlUpdate;public class UpdateCreditRating extends SqlUpdate {public UpdateCreditRating(DataSource ds) {setDataSource(ds);setSql("update customer set credit_rating = ? where id = ?");declareParameter(new SqlParameter(Types.NUMERIC));declareParameter(new SqlParameter(Types.NUMERIC));compile();}/*** @param id for the Customer to be updated* @param rating the new value for credit rating* @return number of rows updated*/public int run(int id, int rating) {Object[] params =new Object[] {new Integer(rating),new Integer(id)};return update(params);} }

10.4.4.?StoredProcedure

這是RDBMS存儲(chǔ)過程的對(duì)象抽象的超類。它是一個(gè)抽象類,它的執(zhí)行方法都是protected的, 以避免被直接調(diào)用,而只能通過提供更嚴(yán)格形式的子類調(diào)用。

繼承的sql屬性是RDBMS中存儲(chǔ)過程的名字。雖然這個(gè)類中提供的其他功能在JDBC3.0中也十分的重要, 但最值得注意的是JDBC3.0中的使用命名的參數(shù)。

下面是一段例子程序,它調(diào)用Oracle數(shù)據(jù)庫(kù)提供的函數(shù)sysdate()。 要使用存儲(chǔ)過程的功能,你必須創(chuàng)建一個(gè)繼承StoredProcedure的類. 這里沒有任何輸入?yún)?shù),但需要使用SqlOutParameter類聲明一個(gè)date型的輸出參數(shù)。?execute()方法會(huì)返回一個(gè)使用名字作為key來映射每一個(gè)被聲明的輸出參數(shù)的實(shí)體的Map。

import java.sql.Types; import java.util.HashMap; import java.util.Iterator; import java.util.Map;import javax.sql.DataSource;import org.springframework.jdbc.core.SqlOutParameter; import org.springframework.jdbc.datasource.*; import org.springframework.jdbc.object.StoredProcedure;public class TestSP {public static void main(String[] args) {System.out.println("DB TestSP!");TestSP t = new TestSP();t.test();System.out.println("Done!");}void test() {DriverManagerDataSource ds = new DriverManagerDataSource();ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");ds.setUrl("jdbc:oracle:thin:@localhost:1521:mydb");ds.setUsername("scott");ds.setPassword("tiger");MyStoredProcedure sproc = new MyStoredProcedure(ds);Map res = sproc.execute();printMap(res);}private class MyStoredProcedure extends StoredProcedure {public static final String SQL = "sysdate";public MyStoredProcedure(DataSource ds) {setDataSource(ds);setFunction(true);setSql(SQL);declareParameter(new SqlOutParameter("date", Types.DATE));compile();}public Map execute() {Map out = execute(new HashMap());return out;}}private static void printMap(Map r) {Iterator i = r.entrySet().iterator();while (i.hasNext()) {System.out.println((String) i.next().toString()); }} }

10.4.5.?SqlFunction

SQL "function"封裝返回單一行結(jié)果的查詢。默認(rèn)的情況返回一個(gè)int,當(dāng)然我們可以重載它, 通過額外返回參數(shù)得到其他類型。這和使用JdbcTemplate的?queryForXxx方法很相似。使用SqlFunction的好處是 不用必須在后臺(tái)建立JdbcTemplate。

這個(gè)類的目的是調(diào)用SQL function,使用像"select user()"或者"select sysdate from dual" 得到單一的結(jié)果。它不是用來調(diào)用復(fù)雜的存儲(chǔ)功能也不是用來使用CallableStatement?來調(diào)用存儲(chǔ)過程或者存儲(chǔ)功能。對(duì)于這類的處理應(yīng)當(dāng)使用StoredProcedure或者SqlCall。

這是一個(gè)具體的類,它通常不需要子類化。使用這個(gè)包的代碼可以通過聲明SQL和參數(shù)創(chuàng)建這個(gè)類型的對(duì)象, 然后能重復(fù)的使用run方法執(zhí)行這個(gè)function。下面是一個(gè)得到一張表的行數(shù)的例子:

public int countRows() {SqlFunction sf = new SqlFunction(dataSource, "select count(*) from mytable");sf.compile();return sf.run();} from: http://docs.huihoo.com/spring/zh-cn/jdbc.html 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的Spring - Java/J2EE Application Framework 应用框架 第 10 章 使用JDBC进行数据访问的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。