在JavaEE應用程序中,數據源對象(DataSource objects)是通過JDBC API訪問關系數據庫的途徑。每個DataSource對象都有一系列用來描述現實世界中數據源的屬性,通過這些屬性可以描述數據庫服務器所在的地址、數據庫名稱、網絡協議等信息。另外數據源對象還可以與JNDI配合使用,如果將一個數據源與一個注冊好的JNDI服務綁定後,在應用程序中就可以通過訪問JNDI API得到這個數據源對象,進而取得和數據庫的鏈接以及進行數據庫操作。
在JavaEE 6以前,數據源的定義和使用與Java應用服務器廠家有很強的相關性,JavaEE 6則提供了更為靈活的數據源定義方式,可以定義在多個應用服務器之間兼容的數據源。另外同時支持注釋、聲明、部署表述等多個定義方式。在本文中,將說明如何使用注釋和或部署描述來定義數據源。
使用注釋定義數據源
在JavaEE 6中提供了兩個用來定義數據源的注釋標記:@DataSourceDefinition 和@DataSourceDefinitions,這兩個標記都位於Javax.annotation.sql包中。通過@DataSourceDefinition可以定義單個數據源,通過@DataSourceDefinitions可以定義多個數據源。
@DataSourceDefinition注釋
@DataSourceDefinition注釋標記可以應用客戶端、Servlet、EJB等元件當中定義數據源,通過該注釋標記,可以定義數據源對象,並與JNDK綁定。該標記的使用方式與設置數據源對象的屬性沒有什麼區別,也可以設置附加信息以及特定信息。
例如,下面的注釋標記創建了一個訪問Derby數據庫的數據源。
- @DataSourceDefinition(name = "Java:app/env/Servlet_DataSource",
- minPoolSize = 0,
- initialPoolSize = 0,
- className = "org.apache.derby.jdbc.ClIEntXADataSource",
- user = "APP",
- passWord = "APP",
- databaseName = "testdb",
- propertIEs = {"connectionAttributes=;create=true"}
- )
數據源的name屬性值就是要綁定的的JNDI名稱,根據JNDI的特點,該值應該是唯一的。從上面的例子中可以注意到,屬性值的第一部分,也就是java:app是一個命名空間說明。在JavaEE 6中引入了應用元件命名空間,目前可以使用的命名空間如下:
Java:comp,同一應用同一容器中的元件可以訪問。
Java:module,與元件相同的一個模塊中可以訪問,比如定義在同一個ejb-jar.XML中的EJB元件。
Java:app,可以在同一應用中的所有元件和模塊中訪問,例如位於統一ear文件中的客戶端元件、WEB元件、EJB元件。
Java:global,可以在服務器中所有的應用程序之間共享。
name屬性所引用的命名空間范圍,也決定了數據源對象的訪問范圍,也就是模塊、應用或者同一服務中的所有用用。以下的定義方式分別表示:
Java:comp/env/, 與數據源定義元件處於同一容器中的其他元件、如客戶端元件、WEB元件、EJB元件都可以訪問這個數據源。
Java:module/env/, 位於同一個ejb-jar.XML中的元件都可以訪問這個數據源。
Java:app/env/, 同一個應用中的所有元件,如EJB, servlet以及客戶端元件都可以訪問這個數據源。
@DataSourceDefinitions注釋
通過@DataSourceDefinitions可以在一個元件類中創建多個數據源,就如同定義一個數組一樣,每個數據源是數組的一個元素。下面是一個為EJB定義多個數據源的例子。
- @DataSourceDefinitions(
- value = {
- @DataSourceDefinition(name = "Java:app/env/HelloStatefulEJB_DataSource",
- minPoolSize = 0,
- initialPoolSize = 0,
- className = "org.apache.derby.jdbc.ClIEntXADataSource",
- portNumber = 1527,
- serverName = "localhost",
- user = "APP",
- passWord = "APP",
- databaseName = "testdb",
- propertIEs = {"connectionAttributes=;create=true"}
- ),
- @DataSourceDefinition(name = "Java:comp/env/HelloStatefulEJB_DataSource",
- minPoolSize = 0,
- initialPoolSize = 0,
- className = "org.apache.derby.jdbc.ClIEntXADataSource",
- portNumber = 1527,
- serverName = "localhost",
- user = "APP",
- passWord = "APP",
- databaseName = "testdb",
- propertIEs = {"connectionAttributes=;create=true"}
- )
- }
- )
- @Stateful
- public class HelloStatefulEJB implements HelloStateful {
- ...
- ...
- }
采用部署表述定義數據源
除了前面的方式以外,JavaEE 6還繼續支持使用部署描述的方式定義數據源,部署描述信息可以寫在application.xml、application-clIEnt.xml、web.xml以及ejb-jar.XML當中。下面的例子中定義的數據源與前面使用@DataSourceDefinition數據源含義相同。
- <data-source>
- <name>Java:app/env/Application_Level_DataSource</name>
- <class-name>org.apache.derby.jdbc.ClIEntXADataSource</class-name>
- <server-name>localhost</server-name>
- <port-number>1527</port-number>
- <database-name>testdb</database-name>
- <user>APP</user>
- <passWord>APP</passWord>
- <property>
- <name>connectionAttributes</name>
- <value>;create=true</value>
- </property>
- </data-source>
如果在同一個應用程序中,分別通過@DataSourceDefinition和部署描述信息定義了兩個數據源,但這這兩個數據源具有相同的name屬性。如果發證這樣的情況,采用部署描述定義的數據源優先權高於采用注釋聲明定義的數據源。