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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

java

Java DataSource对象

發(fā)布時(shí)間:2023/12/20 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java DataSource对象 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

連接數(shù)據(jù)源對(duì)象

本節(jié)介紹DataSource對(duì)象,這是獲得與數(shù)據(jù)源的連接的首選方法。除了它們的其他優(yōu)點(diǎn)(將在后面解釋)之外,DataSource對(duì)象還可以提供連接池和分布式事務(wù)。此功能對(duì)于企業(yè)數(shù)據(jù)庫(kù)計(jì)算至關(guān)重要。特別是,它是Enterprise JavaBeans(EJB)技術(shù)不可或缺的。

本節(jié)向您展示如何使用該DataSource接口獲得連接以及如何使用分布式事務(wù)和連接池。兩者都涉及JDBC應(yīng)用程序中很少的代碼更改。

系統(tǒng)管理員通常使用工具(例如Apache Tomcat或Oracle WebLogic Server)來(lái)部署使這些操作成為可能的類而執(zhí)行的工作因要部署的DataSource對(duì)象類型而異。因此,本節(jié)的大部分內(nèi)容專門介紹系統(tǒng)管理員如何設(shè)置環(huán)境,以便程序員可以使用DataSource對(duì)象來(lái)獲得連接。

涵蓋以下主題:

  • 使用數(shù)據(jù)源對(duì)象獲取連接
  • 部署基本數(shù)據(jù)源對(duì)象
  • 部署其他數(shù)據(jù)源實(shí)現(xiàn)
  • 獲取和使用池化連接
  • 部署分布式事務(wù)
  • 使用連接進(jìn)行分布式事務(wù)

使用數(shù)據(jù)源對(duì)象獲取連接

在建立連接中,您學(xué)習(xí)了如何使用DriverManager該類來(lái)獲得連接。本節(jié)說(shuō)明如何使用DataSource對(duì)象來(lái)建立與數(shù)據(jù)源的連接,這是首選方法。

由實(shí)現(xiàn)的類實(shí)例化的對(duì)象DataSource表示特定的DBMS或某些其他數(shù)據(jù)源,例如文件。甲DataSource對(duì)象表示一個(gè)特定的DBMS或一些其它數(shù)據(jù)源,諸如一個(gè)文件。如果公司使用多個(gè)數(shù)據(jù)源,它將DataSource為每個(gè)數(shù)據(jù)源部署一個(gè)單獨(dú)的對(duì)象。該DataSource接口由驅(qū)動(dòng)程序供應(yīng)商實(shí)現(xiàn)。它可以通過(guò)三種不同的方式實(shí)現(xiàn):

  • 基本DataSource實(shí)現(xiàn)產(chǎn)生的標(biāo)準(zhǔn)Connection對(duì)象沒(méi)有在分布式事務(wù)中合并或使用。
  • 甲DataSource實(shí)現(xiàn),它支持連接池產(chǎn)生Connection參與連接池,即,可循環(huán)使用的連接對(duì)象。
  • 阿DataSource那分布式支持事務(wù)執(zhí)行產(chǎn)生Connection,可以在分布式事務(wù),即,訪問(wèn)兩個(gè)或多個(gè)DBMS服務(wù)器事務(wù)中使用的對(duì)象。

JDBC驅(qū)動(dòng)程序應(yīng)至少包括一個(gè)基本DataSource實(shí)現(xiàn)。例如,Java DB JDBC驅(qū)動(dòng)程序包括org.apache.derby.jdbc.ClientDataSourceMySQL的實(shí)現(xiàn)和com.mysql.jdbc.jdbc2.optional.MysqlDataSource。如果您的客戶端在Java 8 Compact Profile 2上運(yùn)行,則Java DB JDBC驅(qū)動(dòng)程序?yàn)閛rg.apache.derby.jdbc.BasicClientDataSource40。本教程的示例要求壓縮配置文件3或更高。

一DataSource類是支持分布式事務(wù)通常也實(shí)現(xiàn)了連接池支持。例如,DataSourceEJB供應(yīng)商提供的類幾乎總是支持連接池和分布式事務(wù)。

假設(shè)從前面的示例來(lái)看,The Coffee Break商店蓬勃發(fā)展的連鎖店的所有者已決定通過(guò)在Internet上出售咖啡來(lái)進(jìn)一步擴(kuò)大規(guī)模。預(yù)期會(huì)有大量的在線業(yè)務(wù),因此所有者肯定需要連接池。打開(kāi)和關(guān)閉連接會(huì)涉及大量開(kāi)銷,并且所有者希望此在線訂購(gòu)系統(tǒng)需要大量的查詢和更新。使用連接池,可以反復(fù)使用連接池,從而避免了為每次數(shù)據(jù)庫(kù)訪問(wèn)創(chuàng)建新連接的開(kāi)銷。此外,所有者現(xiàn)在擁有第二個(gè)DBMS,其中包含最近收購(gòu)的咖啡烘焙公司的數(shù)據(jù)。這意味著所有者將希望能夠編寫(xiě)使用舊DBMS服務(wù)器和新DBMS服務(wù)器的分布式事務(wù)。

鏈所有者已重新配置計(jì)算機(jī)系統(tǒng),以服務(wù)于新的更大的客戶群。所有者購(gòu)買了最新的JDBC驅(qū)動(dòng)程序和與其一起使用的EJB應(yīng)用程序服務(wù)器,以便能夠使用分布式事務(wù)并獲得連接池帶來(lái)的更高性能。提供了許多與最近購(gòu)買的EJB服務(wù)器兼容的JDBC驅(qū)動(dòng)程序。所有者現(xiàn)在具有三層體系結(jié)構(gòu),中間層是新的EJB應(yīng)用程序服務(wù)器和JDBC驅(qū)動(dòng)程序,第三層是兩個(gè)DBMS服務(wù)器。發(fā)出請(qǐng)求的客戶端計(jì)算機(jī)是第一層。

部署基本數(shù)據(jù)源對(duì)象

系統(tǒng)管理員需要部署DataSource對(duì)象,以便Coffee Break的編程團(tuán)隊(duì)可以開(kāi)始使用它們。部署DataSource對(duì)象包括三個(gè)任務(wù):

  • 創(chuàng)建DataSource類的實(shí)例
  • 設(shè)置其屬性
  • 在使用Java命名和目錄接口(JNDI)API的命名服務(wù)中注冊(cè)它
  • 首先,考慮最基本的情況,即使用DataSource接口的基本實(shí)現(xiàn),即不支持連接池或分布式事務(wù)的接口。在這種情況下,僅DataSource需要部署一個(gè)對(duì)象。基本的實(shí)現(xiàn)DataSource產(chǎn)生與類產(chǎn)生的相同類型的連接DriverManager。

    創(chuàng)建數(shù)據(jù)源類的實(shí)例并設(shè)置其屬性

    假設(shè)一家只希望基本實(shí)現(xiàn)的DataSource公司從JDBC供應(yīng)商DB Access,Inc.購(gòu)買了一個(gè)驅(qū)動(dòng)程序。該驅(qū)動(dòng)程序包括com.dbaccess.BasicDataSource實(shí)現(xiàn)該DataSource接口的類。以下代碼摘錄創(chuàng)建該類的實(shí)例BasicDataSource并設(shè)置其屬性。BasicDataSource部署完實(shí)例之后,程序員可以調(diào)用該方法DataSource.getConnection來(lái)獲取與公司數(shù)據(jù)庫(kù)的連接CUSTOMER_ACCOUNTS。首先,系統(tǒng)管理員使用默認(rèn)構(gòu)造函數(shù)創(chuàng)建BasicDataSource對(duì)象ds。然后,系統(tǒng)管理員設(shè)置三個(gè)屬性。請(qǐng)注意,以下代碼通常由部署工具執(zhí)行:

    com.dbaccess.BasicDataSource ds = new com.dbaccess.BasicDataSource(); ds.setServerName("grinder"); ds.setDatabaseName("CUSTOMER_ACCOUNTS"); ds.setDescription("Customer accounts database for billing");

    ds現(xiàn)在,該變量表示CUSTOMER_ACCOUNTS服務(wù)器上安裝的數(shù)據(jù)庫(kù)。該BasicDataSource對(duì)象產(chǎn)生的任何連接ds都將是與數(shù)據(jù)庫(kù)的連接CUSTOMER_ACCOUNTS。

    向使用JNDI API的命名服務(wù)注冊(cè)數(shù)據(jù)源對(duì)象

    通過(guò)設(shè)置屬性,系統(tǒng)管理員可以向BasicDataSourceJNDI(Java命名和目錄接口)命名服務(wù)注冊(cè)對(duì)象。通常使用的特定命名服務(wù)由系統(tǒng)屬性確定,此處未顯示。以下代碼摘錄注冊(cè)該BasicDataSource對(duì)象并將其與邏輯名綁定jdbc/billingDB:

    Context ctx = new InitialContext(); ctx.bind("jdbc/billingDB", ds);

    此代碼使用JNDI API。第一行創(chuàng)建一個(gè)InitialContext對(duì)象,該對(duì)象用作名稱的起點(diǎn),類似于文件系統(tǒng)中的根目錄。第二行將BasicDataSource對(duì)象關(guān)聯(lián)或綁定ds到邏輯名jdbc/billingDB。在下一個(gè)代碼摘錄中,為命名服務(wù)賦予此邏輯名,然后它返回BasicDataSource對(duì)象。邏輯名稱可以是任何字符串。在這種情況下,公司決定使用該名稱billingDB作為CUSTOMER_ACCOUNTS數(shù)據(jù)庫(kù)的邏輯名稱。

    在前面的示例中,jdbc是初始上下文下的子上下文,就像根目錄下的目錄是子目錄一樣。該名稱jdbc/billingDB類似于路徑名,其中路徑中的最后一項(xiàng)類似于文件名。在這種情況下,billingDB是賦予BasicDataSource對(duì)象的邏輯名ds。子上下文jdbc是保留給邏輯名綁定到DataSource對(duì)象的,因此jdbc它將始終是數(shù)據(jù)源邏輯名的第一部分。

    使用部署的數(shù)據(jù)源對(duì)象

    在DataSource系統(tǒng)管理員部署了基本實(shí)現(xiàn)之后,程序員就可以使用它了。這意味著程序員可以提供綁定到DataSource類實(shí)例的邏輯數(shù)據(jù)源名稱,并且JNDI命名服務(wù)將返回DataSource該類的實(shí)例。getConnection然后可以在該DataSource對(duì)象上調(diào)用該方法以獲取與其表示的數(shù)據(jù)源的連接。例如,程序員可能編寫(xiě)以下兩行代碼來(lái)獲取一個(gè)DataSource對(duì)象,該對(duì)象產(chǎn)生與數(shù)據(jù)庫(kù)的連接CUSTOMER_ACCOUNTS。

    Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/billingDB");

    代碼的第一行以初始上下文為檢索DataSource對(duì)象的起點(diǎn)。在jdbc/billingDB為方法提供邏輯名時(shí)lookup,該方法將返回DataSource系統(tǒng)管理員jdbc/billingDB在部署時(shí)綁定到的對(duì)象。因?yàn)樵摲椒ǖ姆祷刂祃ookup是Java?Object,所以DataSource在將其分配給變量之前,必須將其轉(zhuǎn)換為更特定的類型ds。

    變量ds是com.dbaccess.BasicDataSource實(shí)現(xiàn)DataSource接口的類的實(shí)例。調(diào)用該方法將ds.getConnection產(chǎn)生與CUSTOMER_ACCOUNTS數(shù)據(jù)庫(kù)的連接。

    Connection con = ds.getConnection("fernanda","brewed");

    該getConnection方法僅需要用戶名和密碼,因?yàn)樵撟兞吭谄鋵傩灾衐s具有與CUSTOMER_ACCOUNTS數(shù)據(jù)庫(kù)建立連接所需的其余信息,例如數(shù)據(jù)庫(kù)名稱和位置。

    數(shù)據(jù)源對(duì)象的優(yōu)點(diǎn)

    由于其屬性,DataSource與DriverManager用于連接的類相比,對(duì)象是更好的替代方法。程序員不再需要在其應(yīng)用程序中對(duì)驅(qū)動(dòng)程序名稱或JDBC URL進(jìn)行硬編碼,從而使它們更易于移植。而且,DataSource屬性使代碼維護(hù)更加簡(jiǎn)單。如果進(jìn)行了更改,則系統(tǒng)管理員可以更新數(shù)據(jù)源屬性,而不必?fù)?dān)心更改與該數(shù)據(jù)源建立連接的每個(gè)應(yīng)用程序。例如,如果將數(shù)據(jù)源移動(dòng)到其他服務(wù)器,則系統(tǒng)管理員要做的就是將serverName屬性設(shè)置為新的服務(wù)器名稱。

    除了可移植性和易于維護(hù)之外,使用DataSource對(duì)象進(jìn)行連接還可以提供其他優(yōu)點(diǎn)。當(dāng)實(shí)現(xiàn)DataSource接口以與實(shí)現(xiàn)一起使用ConnectionPoolDataSource時(shí),DataSource該類實(shí)例產(chǎn)生的所有連接將自動(dòng)為池連接。類似地,當(dāng)DataSource實(shí)現(xiàn)被實(shí)現(xiàn)為與XADataSource類一起使用時(shí),它產(chǎn)生的所有連接將自動(dòng)為可在分布式事務(wù)中使用的連接。下一節(jié)將說(shuō)明如何部署這些類型的DataSource實(shí)現(xiàn)。

    部署其他數(shù)據(jù)源實(shí)現(xiàn)

    系統(tǒng)管理員或以該身份工作的其他人可以部署DataSource對(duì)象,以便它產(chǎn)生的連接為池連接。為此,他(她)首先部署一個(gè)ConnectionPoolDataSource對(duì)象,然后部署一個(gè)DataSource實(shí)現(xiàn)為可以使用的對(duì)象。ConnectionPoolDataSource設(shè)置對(duì)象的屬性,使其代表將與其建立連接的數(shù)據(jù)源。將ConnectionPoolDataSource對(duì)象注冊(cè)到JNDI命名服務(wù)后,將DataSource部署對(duì)象。通常,僅需為該DataSource對(duì)象設(shè)置兩個(gè)屬性:description和dataSourceName。賦予該dataSourceName屬性的值是標(biāo)識(shí)ConnectionPoolDataSource先前部署的對(duì)象的邏輯名,該邏輯名是包含進(jìn)行連接所需的屬性的對(duì)象。

    隨著ConnectionPoolDataSource與DataSource對(duì)象部署,您可以調(diào)用該方法DataSource.getConnection上DataSource的對(duì)象,并得到一個(gè)連接池。此連接將連接到ConnectionPoolDataSource對(duì)象屬性中指定的數(shù)據(jù)源。

    以下示例描述了The Coffee Break的系統(tǒng)管理員如何部署DataSource實(shí)現(xiàn)為提供池化連接的對(duì)象。系統(tǒng)管理員通常會(huì)使用部署工具,因此本節(jié)中顯示的代碼片段是部署工具將執(zhí)行的代碼。

    為了獲得更好的性能,Coffee Break公司從DB Access,Inc.購(gòu)買了JDBC驅(qū)動(dòng)程序com.dbaccess.ConnectionPoolDS,其中包括實(shí)現(xiàn)該ConnectionPoolDataSource接口的class?。系統(tǒng)管理員創(chuàng)建創(chuàng)建此類的實(shí)例,設(shè)置其屬性,并將其注冊(cè)到JNDI命名服務(wù)。Coffee Break從其EJB服務(wù)器供應(yīng)商Application Logic,Inc.購(gòu)買了其DataSource類com.applogic.PooledDataSource。該類com.applogic.PooledDataSource使用ConnectionPoolDataSource該類提供的基礎(chǔ)支持來(lái)實(shí)現(xiàn)連接池com.dbaccess.ConnectionPoolDS。

    該ConnectionPoolDataSource對(duì)象必須首先部署。以下代碼創(chuàng)建的實(shí)例com.dbaccess.ConnectionPoolDS并設(shè)置其屬性:

    com.dbaccess.ConnectionPoolDS cpds = new com.dbaccess.ConnectionPoolDS(); cpds.setServerName("creamer"); cpds.setDatabaseName("COFFEEBREAK"); cpds.setPortNumber(9040); cpds.setDescription("Connection pooling for " + "COFFEEBREAK DBMS");

    ConnectionPoolDataSource部署對(duì)象后,系統(tǒng)管理員將部署DataSource對(duì)象。以下代碼向JNDI命名服務(wù)注冊(cè)com.dbaccess.ConnectionPoolDS對(duì)象cpds。請(qǐng)注意,與cpds變量關(guān)聯(lián)的邏輯名具有在子上下文pool下添加的子上下文jdbc,這類似于將子目錄添加到分層文件系統(tǒng)中的另一個(gè)子目錄。該類的任何實(shí)例的邏輯名稱com.dbaccess.ConnectionPoolDS始終以開(kāi)頭jdbc/pool。Oracle建議將所有ConnectionPoolDataSource對(duì)象放在子上下文下jdbc/pool:

    Context ctx = new InitialContext(); ctx.bind("jdbc/pool/fastCoffeeDB", cpds);

    接下來(lái),部署DataSource實(shí)現(xiàn)為與cpds變量和com.dbaccess.ConnectionPoolDS該類的其他實(shí)例交互的類。以下代碼創(chuàng)建此類的實(shí)例并設(shè)置其屬性。請(qǐng)注意,僅為此實(shí)例設(shè)置了兩個(gè)屬性com.applogic.PooledDataSource。description設(shè)置該屬性是因?yàn)樗冀K是必需的。設(shè)置的另一個(gè)屬性dataSourceName給出了的邏輯JNDI名稱cpds,它是com.dbaccess.ConnectionPoolDS該類的實(shí)例。換句話說(shuō),cpds表示ConnectionPoolDataSource將為對(duì)象實(shí)現(xiàn)連接池的DataSource對(duì)象。

    以下代碼(可能由部署工具執(zhí)行)創(chuàng)建一個(gè)PooledDataSource對(duì)象,設(shè)置其屬性,并將其綁定到邏輯名稱jdbc/fastCoffeeDB:

    com.applogic.PooledDataSource ds = new com.applogic.PooledDataSource(); ds.setDescription("produces pooled connections to COFFEEBREAK"); ds.setDataSourceName("jdbc/pool/fastCoffeeDB"); Context ctx = new InitialContext(); ctx.bind("jdbc/fastCoffeeDB", ds);

    此時(shí),將DataSource部署一個(gè)對(duì)象,應(yīng)用程序可以從該對(duì)象獲得與數(shù)據(jù)庫(kù)的池化連接COFFEEBREAK。

    獲取和使用池化連接

    一個(gè)連接池是數(shù)據(jù)庫(kù)連接對(duì)象的緩存。這些對(duì)象表示物理數(shù)據(jù)庫(kù)連接,應(yīng)用程序可以使用這些物理數(shù)據(jù)庫(kù)連接來(lái)連接數(shù)據(jù)庫(kù)。在運(yùn)行時(shí),應(yīng)用程序請(qǐng)求池中的連接。如果池包含可以滿足請(qǐng)求的連接,則它將連接返回給應(yīng)用程序。如果未找到任何連接,則會(huì)創(chuàng)建一個(gè)新的連接并返回到應(yīng)用程序。應(yīng)用程序使用該連接在數(shù)據(jù)庫(kù)上執(zhí)行某些工作,然后將對(duì)象返回到池中。然后,該連接可用于下一個(gè)連接請(qǐng)求。

    連接池可促進(jìn)連接對(duì)象的重用,并減少創(chuàng)建連接對(duì)象的次數(shù)。連接池顯著提高了數(shù)據(jù)庫(kù)密集型應(yīng)用程序的性能,因?yàn)閯?chuàng)建連接對(duì)象在時(shí)間和資源上都非常昂貴。

    現(xiàn)在這些DataSource和ConnectionPoolDataSource對(duì)象的部署,程序員可以使用DataSource對(duì)象來(lái)獲取連接池。獲取池化連接的代碼與獲取非池化連接的代碼一樣,如以下兩行所示:

    ctx = new InitialContext(); ds = (DataSource)ctx.lookup("jdbc/fastCoffeeDB");

    該變量ds表示一個(gè)DataSource對(duì)象,該對(duì)象產(chǎn)生與數(shù)據(jù)庫(kù)的池化連接COFFEEBREAK。您只需要檢索DataSource一次該對(duì)象,因?yàn)槟梢允褂盟鼇?lái)產(chǎn)生所需的任意多個(gè)池連接。getConnection在ds變量上調(diào)用方法會(huì)自動(dòng)產(chǎn)生一個(gè)池化連接,因?yàn)镈ataSource該ds變量代表的對(duì)象已配置為產(chǎn)生池化連接。

    連接池通常對(duì)程序員是透明的。使用池連接時(shí),只需要做兩件事:

  • 使用DataSource對(duì)象而不是DriverManager類來(lái)獲得連接。在下面的代碼行中,ds是一個(gè)DataSource對(duì)象的實(shí)現(xiàn)和部署,以便它將創(chuàng)建池連接,username并且password是代表有權(quán)訪問(wèn)數(shù)據(jù)庫(kù)的用戶憑據(jù)的變量:

    Connection con = ds.getConnection(username, password);
  • 使用finally語(yǔ)句關(guān)閉池化連接。在適用于使用池化連接的代碼的代碼塊finally之后,將出現(xiàn)以下try/catch代碼塊:

    try {Connection con = ds.getConnection(username, password);// ... code to use the pooled// connection con } catch (Exception ex {// ... code to handle exceptions } finally {if (con != null) con.close(); }
  • 否則,使用池連接的應(yīng)用程序與使用常規(guī)連接的應(yīng)用程序相同。應(yīng)用程序程序員在完成連接池時(shí)可能會(huì)注意到的唯一另一件事是性能更好。

    以下示例代碼獲取一個(gè)DataSource對(duì)象,該對(duì)象產(chǎn)生與數(shù)據(jù)庫(kù)的連接,COFFEEBREAK并使用它來(lái)更新表中的價(jià)格COFFEES:

    import java.sql.*; import javax.sql.*; import javax.ejb.*; import javax.naming.*;public class ConnectionPoolingBean implements SessionBean {// ...public void ejbCreate() throws CreateException {ctx = new InitialContext();ds = (DataSource)ctx.lookup("jdbc/fastCoffeeDB");}public void updatePrice(float price, String cofName,String username, String password)throws SQLException{Connection con;PreparedStatement pstmt;try {con = ds.getConnection(username, password);con.setAutoCommit(false);pstmt = con.prepareStatement("UPDATE COFFEES " +"SET PRICE = ? " +"WHERE COF_NAME = ?");pstmt.setFloat(1, price);pstmt.setString(2, cofName);pstmt.executeUpdate();con.commit();pstmt.close();} finally {if (con != null) con.close();}}private DataSource ds = null;private Context ctx = null; }

    此代碼示例中的連接參與連接池,因?yàn)橐韵率钦_的:

    • 一個(gè)類實(shí)現(xiàn)的實(shí)例ConnectionPoolDataSource已部署。
    • DataSource已經(jīng)部署了一個(gè)類實(shí)現(xiàn)的實(shí)例,并且為其dataSourceName屬性設(shè)置的值是綁定到先前部署的ConnectionPoolDataSource對(duì)象的邏輯名稱。

    請(qǐng)注意,盡管此代碼與您之前看到的代碼非常相似,但在以下方面有所不同:

    • 它進(jìn)口javax.sql,javax.ejb和javax.naming包除java.sql。

      的DataSource和ConnectionPoolDataSource接口處于javax.sql封裝,JNDI構(gòu)造InitialContext和方法Context.lookup是的一部分javax.naming封裝。此特定示例代碼采用使用javax.ejb包中API的EJB組件的形式。該示例的目的是說(shuō)明使用池化連接的方式與使用非池化連接的方式相同,因此您不必?fù)?dān)心理解EJB API。

    • 它使用DataSource對(duì)象來(lái)獲得連接,而不是使用DriverManager設(shè)施。

    • 它使用一個(gè)finally塊來(lái)確保關(guān)閉連接。

    獲取和使用池化連接類似于獲取和使用常規(guī)連接。當(dāng)某人充當(dāng)系統(tǒng)管理員正確部署了一個(gè)ConnectionPoolDataSource對(duì)象和一個(gè)DataSource對(duì)象后,應(yīng)用程序?qū)⑹褂迷揇ataSource對(duì)象來(lái)獲得池化連接。但是,應(yīng)用程序應(yīng)使用finally塊來(lái)關(guān)閉池化連接。為簡(jiǎn)單起見(jiàn),前面的示例使用一個(gè)finally塊,但不使用任何catch塊。如果該try塊中的方法引發(fā)了異常,則默認(rèn)情況下將引發(fā)該異常,finally無(wú)論如何該子句都將執(zhí)行。

    部署分布式事務(wù)

    DataSource可以部署對(duì)象以獲得可在分布式事務(wù)中使用的連接。與連接池一樣,必須部署兩個(gè)不同的類實(shí)例:一個(gè)XADataSource對(duì)象和一個(gè)DataSource實(shí)現(xiàn)為與之協(xié)同工作的對(duì)象。

    假設(shè)The Coffee Break企業(yè)家購(gòu)買的EJB服務(wù)器包含DataSource類com.applogic.TransactionalDS,XADataSource該類與諸如com.dbaccess.XATransactionalDS。它可以與任何XADataSource類一起使用的事實(shí)使EJB服務(wù)器可以跨JDBC驅(qū)動(dòng)程序移植。當(dāng)DataSource與XADataSource物體的部署,產(chǎn)生的連接將能夠參與分布式事務(wù)。在這種情況下,將com.applogic.TransactionalDS實(shí)現(xiàn)該類,以使生成的連接也成為池連接,對(duì)于DataSource作為EJB服務(wù)器實(shí)現(xiàn)的一部分提供的類,通常是這種情況。

    該XADataSource對(duì)象必須首先部署。以下代碼創(chuàng)建的實(shí)例com.dbaccess.XATransactionalDS并設(shè)置其屬性:

    com.dbaccess.XATransactionalDS xads = new com.dbaccess.XATransactionalDS(); xads.setServerName("creamer"); xads.setDatabaseName("COFFEEBREAK"); xads.setPortNumber(9040); xads.setDescription("Distributed transactions for COFFEEBREAK DBMS");

    以下代碼向JNDI命名服務(wù)注冊(cè)com.dbaccess.XATransactionalDS對(duì)象xads。請(qǐng)注意,與之關(guān)聯(lián)的邏輯名稱在下方添加xads了子上下文。Oracle建議類的任何實(shí)例的邏輯名稱始終以開(kāi)頭。xajdbccom.dbaccess.XATransactionalDSjdbc/xa

    Context ctx = new InitialContext(); ctx.bind("jdbc/xa/distCoffeeDB", xads);

    接下來(lái),部署DataSource實(shí)現(xiàn)xads與其他XADataSource對(duì)象交互的對(duì)象。請(qǐng)注意,DataSource類com.applogic.TransactionalDS可以與XADataSource任何JDBC驅(qū)動(dòng)程序供應(yīng)商的類一起使用。部署DataSource對(duì)象涉及創(chuàng)建com.applogic.TransactionalDS類的實(shí)例并設(shè)置其屬性。該dataSourceName屬性設(shè)置為jdbc/xa/distCoffeeDB,與關(guān)聯(lián)的邏輯名稱com.dbaccess.XATransactionalDS。這是實(shí)現(xiàn)XADataSource該類的分布式事務(wù)處理功能的DataSource類。以下代碼部署DataSource該類的實(shí)例:

    com.applogic.TransactionalDS ds = new com.applogic.TransactionalDS(); ds.setDescription("Produces distributed transaction " +"connections to COFFEEBREAK"); ds.setDataSourceName("jdbc/xa/distCoffeeDB"); Context ctx = new InitialContext(); ctx.bind("jdbc/distCoffeeDB", ds);

    既然類的實(shí)例com.applogic.TransactionalDS,并com.dbaccess.XATransactionalDS已經(jīng)部署,應(yīng)用程序可以調(diào)用該方法getConnection的實(shí)例TransactionalDS類來(lái)獲取到的連接COFFEEBREAK可在分布式事務(wù)中使用的數(shù)據(jù)庫(kù)。

    使用連接進(jìn)行分布式事務(wù)

    要獲得可用于分布式事務(wù)的連接,必須使用DataSource已正確實(shí)現(xiàn)和部署的對(duì)象,如“部署分布式事務(wù)”部分中所示。使用這樣的DataSource對(duì)象,對(duì)其調(diào)用方法getConnection。建立連接后,請(qǐng)像使用其他任何連接一樣使用它。由于jdbc/distCoffeesDB已與XADataSourceJNDI命名服務(wù)中的對(duì)象相關(guān)聯(lián),因此以下代碼生成了Connection可在分布式事務(wù)中使用的對(duì)象:

    Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("jdbc/distCoffeesDB"); Connection con = ds.getConnection();

    對(duì)于此連接作為分布式事務(wù)的一部分時(shí)的使用方式,存在一些較小但重要的限制。事務(wù)管理器控制分布式事務(wù)何時(shí)開(kāi)始以及何時(shí)提交或回滾。因此,應(yīng)用程序代碼絕不應(yīng)調(diào)用方法Connection.commit或Connection.rollback。應(yīng)用程序同樣不應(yīng)調(diào)用Connection.setAutoCommit(true),它啟用了自動(dòng)提交模式,因?yàn)檫@也會(huì)干擾事務(wù)管理器對(duì)事務(wù)邊界的控制。這說(shuō)明了為什么在分布式事務(wù)范圍內(nèi)創(chuàng)建的新連接默認(rèn)情況下會(huì)禁用其自動(dòng)提交模式。請(qǐng)注意,這些限制僅在連接參與分布式事務(wù)時(shí)才適用。連接不是分布式事務(wù)的一部分時(shí),沒(méi)有任何限制。

    對(duì)于以下示例,假設(shè)已訂購(gòu)一份咖啡,這將觸發(fā)對(duì)位于不同DBMS服務(wù)器上的兩個(gè)表的更新。第一個(gè)表是一個(gè)新INVENTORY表,第二個(gè)COFFEES表是該表。因?yàn)檫@些表位于不同的DBMS服務(wù)器上,所以涉及它們的事務(wù)將是分布式事務(wù)。以下示例中的代碼(該示例獲得一個(gè)連接,更新該COFFEES表并關(guān)閉該連接)是分布式事務(wù)的第二部分。

    請(qǐng)注意,由于分布式事務(wù)的范圍由中間層服務(wù)器的基礎(chǔ)系統(tǒng)基礎(chǔ)結(jié)構(gòu)控制,因此代碼不會(huì)明確地提交或回退更新。同樣,假設(shè)用于分布式事務(wù)的連接是池化連接,則應(yīng)用程序使用一個(gè)finally塊來(lái)關(guān)閉該連接。這樣可以保證即使拋出異常也將關(guān)閉有效的連接,從而確保將連接返回到連接池以進(jìn)行回收。

    下面的代碼示例說(shuō)明了一個(gè)Enterprise Bean,它是一個(gè)實(shí)現(xiàn)可以由客戶端計(jì)算機(jī)調(diào)用的方法的類。這個(gè)例子的目的是說(shuō)明用于分布式事務(wù)應(yīng)用程序代碼是沒(méi)有從其他代碼不同,除了它不調(diào)用Connection方法commit,rollback或setAutoCommit(true)。因此,您不必?fù)?dān)心了解所使用的EJB API。

    import java.sql.*; import javax.sql.*; import javax.ejb.*; import javax.naming.*;public class DistributedTransactionBean implements SessionBean {// ...public void ejbCreate() throws CreateException {ctx = new InitialContext();ds = (DataSource)ctx.lookup("jdbc/distCoffeesDB");}public void updateTotal(int incr, String cofName, String username,String password)throws SQLException {Connection con;PreparedStatement pstmt;try {con = ds.getConnection(username, password);pstmt = con.prepareStatement("UPDATE COFFEES " +"SET TOTAL = TOTAL + ? " +"WHERE COF_NAME = ?");pstmt.setInt(1, incr);pstmt.setString(2, cofName);pstmt.executeUpdate();stmt.close();} finally {if (con != null) con.close();}}private DataSource ds = null;private Context ctx = null; }

    總結(jié)

    以上是生活随笔為你收集整理的Java DataSource对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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