CallMetaDataProviderFactory 创建CallMetaDataProvider 的工厂类,其代码如下:
public class CallMetaDataProviderFactory {
public static final List<String> supportedDatabaseProductsForProcedures = Arrays.asList("Apache Derby", "DB2", "MySQL", "Microsoft SQL Server", "Oracle", "PostgreSQL", "Sybase");
public static final List<String> supportedDatabaseProductsForFunctions = Arrays.asList("MySQL", "Microsoft SQL Server", "Oracle", "PostgreSQL");
private static final Log logger = LogFactory.getLog(CallMetaDataProviderFactory.class);
public CallMetaDataProviderFactory() {
}
public static CallMetaDataProvider createMetaDataProvider(DataSource dataSource, CallMetaDataContext context) {
try {
CallMetaDataProvider result = (CallMetaDataProvider)JdbcUtils.extractDatabaseMetaData(dataSource, (databaseMetaData) -> {
String databaseProductName = JdbcUtils.commonDatabaseName(databaseMetaData.getDatabaseProductName());
boolean accessProcedureColumnMetaData = context.isAccessCallParameterMetaData();
if (context.isFunction()) {
if (!supportedDatabaseProductsForFunctions.contains(databaseProductName)) {
if (logger.isWarnEnabled()) {
logger.warn(databaseProductName + " is not one of the databases fully supported for function calls -- supported are: " + supportedDatabaseProductsForFunctions);
}
if (accessProcedureColumnMetaData) {
logger.warn("Metadata processing disabled - you must specify all parameters explicitly");
accessProcedureColumnMetaData = false;
}
}
} else if (!supportedDatabaseProductsForProcedures.contains(databaseProductName)) {
if (logger.isWarnEnabled()) {
logger.warn(databaseProductName + " is not one of the databases fully supported for procedure calls -- supported are: " + supportedDatabaseProductsForProcedures);
}
if (accessProcedureColumnMetaData) {
logger.warn("Metadata processing disabled - you must specify all parameters explicitly");
accessProcedureColumnMetaData = false;
}
}
Object provider;
if ("Oracle".equals(databaseProductName)) {
provider = new OracleCallMetaDataProvider(databaseMetaData);
} else if ("DB2".equals(databaseProductName)) {
provider = new Db2CallMetaDataProvider(databaseMetaData);
} else if ("Apache Derby".equals(databaseProductName)) {
provider = new DerbyCallMetaDataProvider(databaseMetaData);
} else if ("PostgreSQL".equals(databaseProductName)) {
provider = new PostgresCallMetaDataProvider(databaseMetaData);
} else if ("Sybase".equals(databaseProductName)) {
provider = new SybaseCallMetaDataProvider(databaseMetaData);
} else if ("Microsoft SQL Server".equals(databaseProductName)) {
provider = new SqlServerCallMetaDataProvider(databaseMetaData);
} else if ("HDB".equals(databaseProductName)) {
provider = new HanaCallMetaDataProvider(databaseMetaData);
} else {
provider = new GenericCallMetaDataProvider(databaseMetaData);
}
if (logger.isDebugEnabled()) {
logger.debug("Using " + provider.getClass().getName());
}
((CallMetaDataProvider)provider).initializeWithMetaData(databaseMetaData);
if (accessProcedureColumnMetaData) {
((CallMetaDataProvider)provider).initializeWithProcedureColumnMetaData(databaseMetaData, context.getCatalogName(), context.getSchemaName(), context.getProcedureName());
}
return provider;
});
return result;
} catch (MetaDataAccessException var3) {
throw new DataAccessResourceFailureException("Error retrieving database metadata", var3);
}
}
}
TableMetaDataProviderFactory 创建TableMetaDataProvider 工厂类,其创建过程如下:
public static TableMetaDataProvider createMetaDataProvider(DataSource dataSource, TableMetaDataContext context) {
try {
TableMetaDataProvider result = (TableMetaDataProvider)JdbcUtils.extractDatabaseMetaData(dataSource, (databaseMetaData) -> {
String databaseProductName = JdbcUtils.commonDatabaseName(databaseMetaData.getDatabaseProductName());
boolean accessTableColumnMetaData = context.isAccessTableColumnMetaData();
Object provider;
if ("Oracle".equals(databaseProductName)) {
provider = new OracleTableMetaDataProvider(databaseMetaData, context.isOverrideIncludeSynonymsDefault());
} else if ("HSQL Database Engine".equals(databaseProductName)) {
provider = new HsqlTableMetaDataProvider(databaseMetaData);
} else if ("PostgreSQL".equals(databaseProductName)) {
provider = new PostgresTableMetaDataProvider(databaseMetaData);
} else if ("Apache Derby".equals(databaseProductName)) {
provider = new DerbyTableMetaDataProvider(databaseMetaData);
} else {
provider = new GenericTableMetaDataProvider(databaseMetaData);
}
if (logger.isDebugEnabled()) {
logger.debug("Using " + provider.getClass().getSimpleName());
}
((TableMetaDataProvider)provider).initializeWithMetaData(databaseMetaData);
if (accessTableColumnMetaData) {
((TableMetaDataProvider)provider).initializeWithTableColumnMetaData(databaseMetaData, context.getCatalogName(), context.getSchemaName(), context.getTableName());
}
return provider;
});
return result;
} catch (MetaDataAccessException var3) {
throw new DataAccessResourceFailureException("Error retrieving database metadata", var3);
}
}
使用SqlParameterSource 提供参数值
使用Map 来指定参数值有时候工作得非常好,但是这并不是最简单的使用方式。Spring提供了一些其他的SqlParameterSource 实现类来指定参数值。我们首先可以看看BeanPropertySqlParameterSource 类,这是一个非常简便的指定参数的实现类,只要你有一个符合JavaBean 规范的类就行了。它将使用其中的getter 方法来获取参数值。
SqlParameter 封装了定义sql 参数的对象。CallableStateMentCallback ,PrePareStateMentCallback,StateMentCallback,ConnectionCallback 回调类分别对应JdbcTemplate 中的不同处理方法。
simple 实现
Spring 通过DataSource 获取数据库的连接。Datasource 是jdbc 规范的一部分,它通过ConnectionFactory 获取。一个容器和框架可以在应用代码层中隐藏连接池和事务管理。
当使用spring 的jdbc 层,你可以通过JNDI 来获取DataSource,也可以通过你自己配置的第三方连接池实现来获取。流行的第三方实现由apache Jakarta Commons dbcp 和c3p0。