AutoSelectNativeJdbcExtractor提供自动选择extractor实例的能力

package com.ejintai.fa.app.integration.jdbc;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;

public class AutoSelectNativeJdbcExtractor
  implements NativeJdbcExtractor, InitializingBean
{
  protected Logger logger = Logger.getLogger(getClass());
  private NativeJdbcExtractor defaultExtractor;
  protected NativeJdbcExtractor jdbcExtractor;
  private Map<String, String> extractorClassMapping;

  public Map<String, String> getExtractorClassMapping()
  {
    return this.extractorClassMapping;
  }

  public void setExtractorClassMapping(Map<String, String> extractorClassMapping) {
    this.extractorClassMapping = extractorClassMapping;
  }

  public NativeJdbcExtractor getDefaultExtractor() {
    return this.defaultExtractor;
  }

  public void setDefaultExtractor(NativeJdbcExtractor defaultExtractor) {
    this.defaultExtractor = defaultExtractor;
  }

  private NativeJdbcExtractor getJdbcExtractor(Object o) {
    if (this.jdbcExtractor == null)
    {
      String objClass = o.getClass().getName();
      NativeJdbcExtractor extractor = null;

      if (this.extractorClassMapping != null) {
        for (String classPrefix : this.extractorClassMapping.keySet()) {
          if (objClass.indexOf(classPrefix) != -1)
          {
            String className = (String)this.extractorClassMapping.get(classPrefix);
            try {
              this.logger.info("尝试实例化extractor:" + className);
              if (className != null) {
                Class clz = getClass().getClassLoader().loadClass(className);
                if (clz != null) {
                  extractor = (InitializingBean)clz.newInstance();
                  break;
                }
              }
            }
            catch (Exception e) {
              this.logger.info("尝试实例化extractor:" + className + "时失败; 忽略该异常,继续尝试下一个", e);
            }
          }
        }
      }
      if (extractor == null) {
        this.logger.info("使用默认的extractor:" + this.defaultExtractor);
        extractor = this.defaultExtractor;
      }

      synchronized (this) {
        if (this.jdbcExtractor == null) {
          this.jdbcExtractor = extractor;
        }
      }
    }
    return this.jdbcExtractor;
  }

  public boolean isNativeConnectionNecessaryForNativeStatements()
  {
    return true;
  }

  public boolean isNativeConnectionNecessaryForNativePreparedStatements()
  {
    return true;
  }

  public boolean isNativeConnectionNecessaryForNativeCallableStatements()
  {
    return true;
  }

  public Connection getNativeConnection(Connection con) throws SQLException
  {
    return getJdbcExtractor(con).getNativeConnection(con);
  }

  public Connection getNativeConnectionFromStatement(Statement stmt)
    throws SQLException
  {
    return getJdbcExtractor(stmt).getNativeConnectionFromStatement(stmt);
  }

  public Statement getNativeStatement(Statement stmt) throws SQLException
  {
    return getJdbcExtractor(stmt).getNativeStatement(stmt);
  }

  public PreparedStatement getNativePreparedStatement(PreparedStatement ps)
    throws SQLException
  {
    return getJdbcExtractor(ps).getNativePreparedStatement(ps);
  }

  public CallableStatement getNativeCallableStatement(CallableStatement cs)
    throws SQLException
  {
    return getJdbcExtractor(cs).getNativeCallableStatement(cs);
  }

  public ResultSet getNativeResultSet(ResultSet rs)
    throws SQLException
  {
    return getJdbcExtractor(rs).getNativeResultSet(rs);
  }

  public void afterPropertiesSet() throws Exception
  {
    if (this.defaultExtractor == null)
      throw new IllegalArgumentException("AutoSelectNativeJdbcExtractor的defaultExtractor属性必须指定");
  }
}

biz-context.xml中:

<!--
    自动根据不同的连接池实现选择对应的nativeJdbcExtractor
    目前支持commons-dbcp,tomcat-dbcp,tomcat7-pool,WAS Connection Pool
    Need JTFA 2.4.0+
    -->
    <bean id="nativeJdbcExtractor" class="com.ejintai.fa.app.integration.jdbc.AutoSelectNativeJdbcExtractor" >
    <property name="defaultExtractor">
    <bean class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor" />
    </property>
    <property name="extractorClassMapping">
    <map>
    <entry key="org.apache.commons.dbcp" value="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>
    <entry key="org.apache.tomcat.dbcp" value="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>
    <entry key="com.ibm" value="org.springframework.jdbc.support.nativejdbc.WebSphereNativeJdbcExtractor"/>
    </map>
    </property>
    </bean>

自动匹配原理和规则 该类进行自动匹配的原理是,在获取到(被连接池”包装过的”)Connection对象后,根据连接的”包装类”的包名前缀来判断当前使用的是哪一种连接池,并根据配置的 包名前缀–Extractor实现类 映射关系获取到要使用的NativeJdbcExtractor实现。


经过测试,我们使用如下匹配关系:

包前缀 NativeJdbcExtractor实现
org.apache.commons.dbcp CommonsDbcpNativeJdbcExtractor
org.apache.tomcat.dbcp CommonsDbcpNativeJdbcExtractor
com.ibm WebSphereNativeJdbcExtractor
default(包括tomcat-pool) SimpleNativeJdbcExtractor

使用范例

同已有代码的使用方式一样,先获取Spring管理的Connection对象,再从中抽取出原始连接

DemoDAOImpl.java:
 
	@Autowired
	private NativeJdbcExtractor nativeJdbcExtractor; 
 
	//如果使用[原始连接]进行操作,请使用@Transactional注解(在DAO或者更外层的Service,Action上应用),让Spring容器来管理连接的释放,
	@Transactional(rollbackFor=DAOException.class)
	@Override
	public String nativeJdbcTest() throws DAOException {
		//使用native connection 调用package
 
		//获取容器管理的[连接池连接],该连接应当由Spring容器关闭, 你应当在DAO或者更外层的Service,Action上使用@Transactional来开启事务
		Connection pooledConn = DataSourceUtils.getConnection(super.getDataSource());
 
		try {
	            //抽取出(原始连接)
	            Connection conn = nativeJdbcExtractor.getNativeConnection(pooledConn); //该连接不应当关闭
 
	            StructDescriptor sd = new StructDescriptor("WEB_FIN_PRM_TYPE", conn);
	            STRUCT[] struct = new STRUCT[1];
	            struct[0]=new STRUCT(sd,conn, getTestValueArray());
 
	            ArrayDescriptor ad = ArrayDescriptor.createDescriptor("TYPE_PRM_DATA_ARRAY", conn);
	            ARRAY array = new ARRAY(ad, conn, struct);
	            OracleCallableStatement callStatement = 
                         (OracleCallableStatement)conn.prepareCall("{call PKG_FINARP_INTERFACE.PROC_INSERT_DATA_TO_PRM(?)}");
	            callStatement.setARRAY(1, array);
	            callStatement.executeUpdate();
 
 
		} catch (SQLException e) {
 
			throw new DAOException(e);
		} 
 
		return "ok";
	}

猜你喜欢

转载自168zsj.iteye.com/blog/1735408