欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-18 09:32:16
...

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";
	}

 

相关标签: dao