The public API for interacting with databases is provided directly in Java SE within the java.sql
package. This package provides the key abstractions corresponding to connections, statements,
result sets, and metadata。
1. JDBC连接数据库
(1)Common entities provided by JDBC:
■ Connection:Corresponds to the connection to the database, allowing the execution of SQL requests
and being responsible for handling local transactions.
■ Statement:Corresponds to the core abstraction for executing all kinds of SQL requests.
■ PreparedStatement :Corresponds to an advanced statement that supports precompiled SQL queries
and parameter specification
■ CallableStatement:CallableStatement Corresponds to a kind of statement enabling you to execute
stored procedures with JDBC.
■ ResultSet:Allows for the parsing of data received on the execution of a SQL query.
■ DatabaseMetaData:Provides access to metadata of the target database.
■ ResultSetMetaData:Provides access to metadata about the types and properties of the columns
contained in a result set
(2)Using JDBC to execute a SQL select request:
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs= null;
try {
connection = getConnection();
String sql = "select id, last_name, first_name" + " from contact" + " where last_name like ?";
statement = connection.prepareStatement(sql);
statement.setString(1, "P%");
rs= statement.executeQuery();
while (rs.next()) {
String contactFirstName= rs.getString("first_name");
String contactLastName= rs.getString("first_name");
}
} catch(Exception ex) {
(...)
} finally {
try {
if (resultSet!=null) {
resultSet.close();
}
} catch(SQLException ex { (...) }
try {
if (statement!=null) {
statement.close();
}
} catch(SQLException ex { (...) }
try {
if (connection!=null) {
connection.close();
}
} catch(SQLException ex { (...) }
}
An extension to JDBC is also available to provide additional support for server-side usage through
the javax.sql package. The more well-known interface of this extension is the DataSource interface,
which corresponds to a connection factory and is commonly used by pool implementations. The
Spring Framework also provides implementations of the DataSource interface within its JDBC
support.
2. JDBC issues when used within OSGi
JDBC的底层实现是驱动程序:
public interface Driver {
boolean acceptsURL(String url);
Connection connect(String url, Properties info);
int getMajorVersion();
int getMinorVersion();
DriverPropertyInfo[] getPropertyInfo(String url, Properties info);
boolean jdbcCompliant();
}
而常见的Java应用程序使用JDBC的主要类是:DriverManager:
Class.forName("org.h2.Driver");
Connection connection = DriverManager.getConnection(
"jdbc:h2:tcp://localhost/springdm-directory","sa", "");
The driver class name is loaded using the static forName method of the Class class. The driver can
then be used to create a JDBC connection using the DriverManager class’s static getConnection
method.
The problem is that the DriverManager class uses classloaders in a specific way that can have
strange side effects within an OSGi container. The class internally checks whether the caller class is
able to instantiate the driver class, and if the caller doesn’t have the required package imports in
its manifest configuration, unexpected ClassNotFoundException exceptions can occur. To avoid this
check, it’s better to not use the DriverManager class within an OSGi container.
The alternative is to use the driver interface directly to obtain a JDBC connection, as shown in the
following snippet. Note that Spring’s ClassUtils and BeanUtils classes can be used to safely
instantiate a JDBC driver from within an OSGi container.
Class driverClass = ClassUtils.resolveClassName(driverClassName,
ClassUtils.getDefaultClassLoader());
Driver driver = (Driver) BeanUtils.instantiateClass(driverClass);
Properties properties = new Properties();
properties.put("user", userName);
properties.put("password", password);
Connection connection = driver.connect(jdbcUrl, properties);
Moreover, when using a pool, you should ensure that it doesn’t use the DriverManager
class. The C3P0 library partially uses the DriverManager class to get a driver and then directly
works with the returned class. In this way, C3P0 uses classloaders correctly from the perspective
of an OSGi container.
3.Configuring JDBC data sources
JDBC provides an abstraction named DataSource, which defines a contract for providing connections.
A DataSource supports provider implementations according to your required resource management
strategy (direct use of driver, pools, and so on).
Different data source implementation strategies for creating JDBC connections:
■ Pool data source
■ DriverManager-based data source
■ Driver-based data source
(1)CONFIGURING A POOL BUNDLE
Database connection pool classes need to see driver packages because the classes contained in
these packages manage the connection resources. By default, the components corresponding to
the pools don’t have the correct OSGi package configuration in their JAR manifest entries. Several
strategies exist to address this issue:
■ During the packaging or OSGi-ification of the pool component, you can add optional import entries
for each package for the possible drivers that you might use. 方法1
■ You can implement a fragment bundle that will add the package containing the driver class that’s
used to the pool component’s manifest configuration.方法2
方法1配置:
Specifying driver packages within the Bnd configuration:
version=1.2.2
Bundle-SymbolicName: org.apache.commons.dbcp
Bundle-Version: ${version}
(...)
Import-Package:org.apache.commons.pool*;version=1.3.0,
org.apache.commons.dbcp*;version=${version},*;resolution:=optional,
org.hsqldb;version="1.8.0.9";resolution:=optional,
org.h2;version="0.0.0";resolution:=optional,
org.postgresql;version="0.0.0";resolution:=optional,
(...)
方法2配置:
The following snippet shows the manifest configuration of a fragment bundle that adds the H2
package to the C3P0 component:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: C3P0 Configuration Fragment
Bundle-SymbolicName:com.springsource.com.mchange.v2.c3p0.config
Bundle-Version: 1.0.0
Bundle-Vendor: Manning
Fragment-Host: com.springsource.com.mchange.v2.c3p0;bundle-version="0.9.1"
Import-Package: org.h2;version="0.0.0"
注意:The SpringSource repository provides a modified version of DBCP that also looks for drivers in
the context classloader. When using this version, you don’t need to add such a fragment, because
the driver will be present in this classloader during the pool’s initialization.
(2)CONFIGURING A DATA SOURCE WITH SPRING DM
Best practice consists of defining a dedicated bundle to configure the data source. Within this
bundle, Spring DM facilities can be used to configure a DataSource instance and register it as an
OSGi service. This service can then be referenced by data access components to interact with
the database.
Configuring a C3P0 pool with Spring DM:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/jdbc.properties"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<osgi:service ref="dataSource" interface="javax.sql.DataSource"/> //导出数据源最为一个OSGi服务
(3)Provisioning the OSGi container for JDBC
Common bundles for Spring JDBC support from SpringSource EBR:
org.springframework.transaction:3.0.5
org.springframework.jdbc:3.0.5
(4)Using JDBC within OSGi with Spring DM
■ REFERENCING JDBC DATA SOURCES IN SPRING DM:
<osgi:reference id="dataSource" interface="javax.sql.DataSource"/>
<osgi:reference id="dataSource" interface="javax.sql.DataSource" filter="(source='database1')"/>
<bean id="contactsDao"
class="com.manning.sdmia.dataaccess.domain.dao.jdbc.ContactsDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
■ USING THE JDBCTEMPLATE CLASS:
DAO structure using the Spring JDBC support:
public class ContactsDaoImpl extends JdbcDaoSupport implements ContactsDao {
public List<Contact> getContacts() {
String sql = (...)
return getJdbcTemplate ().query(sql, new RowMapper() { (...) });
}
(...)
}
需在MAINFEST.MF文件中Import-Package:
Import-Package: (...)
org.springframework.beans.factory;version="3.0.0.M1",
org.springframework.core;version="3.0.0.M1",
org.springframework.dao;version="3.0.0.M1",
org.springframework.jdbc.core;version="3.0.0.M1",
org.springframework.jdbc.core.support;version="3.0.0.M1"
Bootstrap packages(引导包):
The javax.sql package is provided by the OSGi container as a bootstrap package , which means that
you don’t have to specify it explicitly in a bundle. You can specify which of the packages already
present in Java you want by setting your OSGi container’s configuration.
This configuration is specific to the container. For example, the Equinox container requires the use of
the org.osgi.framework.bootdelegation configuration property with a value such as
sun.*,com.sun.*,java.*,javax.*,org.w3c.*.