`

SpringDM笔记20-Using JDBC within OSGi with Spring DM

 
阅读更多

    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.*.

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics