文章目录
- 一、目标:JDBC功能整合
- 二、设计:JDBC功能整合
- 三、实现:JDBC功能整合
- 3.1 工程结构
- 3.2 整合JDBC功能核心类图
- 3.3 数据源操作
- 3.3.1 数据源操作抽象类
- 3.3.2 JDBC 工具类
- 3.4 数据库执行
- 3.4.1 语句处理器接口
- 3.4.2 结果处理器接口
- 3.4.3 行转列结果处理器实现类
- 3.4.4 行映射器接口
- 3.4.5 行列Map映射器实现类
- 3.3.6 数据库执行接口
- 3.5 数据库操作模板
- 3.5.1 SQL提供者
- 3.5.2 JDBC操作抽象类
- 3.5.3 JDBC操作模板
- 四、测试:JDBC功能整合
- 4.1 添加测试配置
- 4.1.1 sql数据库表
- 4.1.2 Spring属性配置文件
- 4.1.3 初始化 Spring和JdbcTemplate对象
- 4.2 单元测试
- 4.2.1 插入测试
- 4.2.2 查询测试
- 五、总结:JDBC功能整合
一、目标:JDBC功能整合
💡 如何结合 Spring 框架,封装 JDBC 并对外提供统一的数据操作模板?
- JDBC 的封装主要实现的是
JdbcTemplate
的功能。Spring 对数据库的操作在 JDBC 上做了深层次的封装。使用 Spring 的注入功能,可以将DataSource
注册到JdbcTemplate
中使用。 JdbcTemplate
主要提供的方法。execute
方法:用于执行任何 SQL 语句,一般用于执行 DDL 语句。update
方法及batchUpdate
方法:update
方法用于执行新增、修改、删除等语句。batchUpdate
方法用于执行与批处理相关的语句。
query
方法及queryForXXX
方法:用于执行与查询相关的语句。call
方法:用于执行与存储过程、函数相关的语句。
二、设计:JDBC功能整合
💡 设计:整合 JDBC 服务
- Spring 框架将与 JDBC 的相关操作封装在
spring-jdbc
模块下的JdbcTemplate
类中调用,并结合 Spring 提供的InitializingBean
接口,在BeanFactory
设置属性后进行相应的自定义初始化处理,将 JDBC 整合到 Spring 框架中。
- DB 连接池提供数据源服务,这里将
DruidDataSource
作为连接池使用。 - 在引入连接池后,基于
JdbcTemplate
完成对数据库的操作处理,包括执行 SQL 语句(如查询、更新和删除数据库表等操作,以及开发对应的数据库表语句)。将执行后的结果进行封装,使用ResultSetExtractor
接口、RowMapper
接口转换数据类型。
三、实现:JDBC功能整合
3.1 工程结构
spring-step-18
|-src
|-main
| |-java
| |-com.lino.springframework
| |-aop
| | |-aspectj
| | | |-AspectJExpressionPointcut.java
| | | |-AspectJExpressionPointcutAdvisor.java
| | |-framework
| | | |-adapter
| | | | |-MethodBeforeAdviceInterceptor.java
| | | |-autoproxy
| | | | |-DefaultAdvisorAutoProxyCreator.java
| | | |-AopProxy.java
| | | |-Cglib2AopProxy.java
| | | |-JdkDynamicAopProxy.java
| | | |-ProxyFactory.java
| | | |-ReflectiveMethodInvocation.java
| | |-AdvisedSupport.java
| | |-Advisor.java
| | |-BeforeAdvice.java
| | |-ClassFilter.java
| | |-MethodBeforeAdvice.java
| | |-MethodMatcher.java
| | |-Pointcut.java
| | |-PointcutAdvisor.java
| | |-TargetSource.java
| |-beans
| | |-factory
| | | |-annotation
| | | | |-Autowired.java
| | | | |-AutowiredAnnotationBeanPostProcessor.java
| | | | |-Qualifier.java
| | | | |-Value.java
| | | |-config
| | | | |-AutowireCapableBeanFactory.java
| | | | |-BeanDefinition.java
| | | | |-BeanFactoryPostProcessor.java
| | | | |-BeanPostProcessor.java
| | | | |-BeanReference.java
| | | | |-ConfigurableBeanFactory.java
| | | | |-InstantiationAwareBeanPostProcessor.java
| | | | |-SingletonBeanRegistry.java
| | | |-support
| | | | |-AbstractAutowireCapableBeanFactory.java
| | | | |-AbstractBeabDefinitionReader.java
| | | | |-AbstractBeabFactory.java
| | | | |-BeabDefinitionReader.java
| | | | |-BeanDefinitionRegistry.java
| | | | |-CglibSubclassingInstantiationStrategy.java
| | | | |-DefaultListableBeanFactory.java
| | | | |-DefaultSingletonBeanRegistry.java
| | | | |-DisposableBeanAdapter.java
| | | | |-FactoryBeanRegistrySupport.java
| | | | |-InstantiationStrategy.java
| | | | |-SimpleInstantiationStrategy.java
| | | |-xml
| | | | |-XmlBeanDefinitionReader.java
| | | |-Aware.java
| | | |-BeanClassLoaderAware.java
| | | |-BeanFactory.java
| | | |-BeanFactoryAware.java
| | | |-BeanNameAware.java
| | | |-ConfigurableListableBeanFactory.java
| | | |-DisposableBean.java
| | | |-FactoryBean.java
| | | |-HierarcgicalBeanFactory.java
| | | |-InitializingBean.java
| | | |-ListableBeanFactory.java
| | | |-ObjectFactory.java
| | | |-PropertyPlaceholderConfigurer.java
| | |-BeansException.java
| | |-PropertyValue.java
| | |-PropertyValues.java
| |-context
| | |-annotation
| | | |-ClassPathBeanDefinitionScanner.java
| | | |-ClassPathScanningCandidateComponentProvider.java
| | | |-Scope.java
| | |-event
| | | |-AbstractApplicationEventMulticaster.java
| | | |-ApplicationContextEvent.java
| | | |-ApplicationEventMulticaster.java
| | | |-ContextclosedEvent.java
| | | |-ContextRefreshedEvent.java
| | | |-SimpleApplicationEventMulticaster.java
| | |-support
| | | |-AbstractApplicationContext.java
| | | |-AbstractRefreshableApplicationContext.java
| | | |-AbstractXmlApplicationContext.java
| | | |-ApplicationContextAwareProcessor.java
| | | |-ClassPathXmlApplicationContext.java
| | | |-ConversionServiceFactoryBean.java
| | |-ApplicationContext.java
| | |-ApplicationContextAware.java
| | |-ApplicationEvent.java
| | |-ApplicationEventPublisher.java
| | |-ApplicationListener.java
| | |-ConfigurableApplicationContext.java
| |-core
| | |-convert
| | | |-converter
| | | | |-Converter.java
| | | | |-ConverterFactory.java
| | | | |-ConverterRegistry.java
| | | | |-GenericConverter.java
| | | |-support
| | | | |-DefaultConversionService.java
| | | | |-GenericConversionService.java
| | | | |-StringToNumberConverterFactory.java
| | | |-ConversionService
| | |-io
| | | |-ClassPathResource.java
| | | |-DefaultResourceLoader.java
| | | |-FileSystemResource.java
| | | |-Resource.java
| | | |-ResourceLoader.java
| | | |-UrlResource.java
| |-jdbc
| | |-core
| | | |-ColumnMapRowMapper.java
| | | |-JdbcOperations.java
| | | |-JdbcTemplate.java
| | | |-ResultSetExtractor.java
| | | |-RowMapper.java
| | | |-RowMapperResultSetExtractor.java
| | | |-SqlProvider.java
| | | |-StatementCallback.java
| | |-datasource
| | | |-DataSourceUtils.java
| | |-support
| | | |-JdbcAccessor.java
| | | |-JdbcUtils.java
| |-stereotype
| | |-Component.java
| |-util
| | |-ClassUtils.java
| | |-NumberUtils.java
| | |-StringValueResolver.java
|-test
|-java
|-com.lino.springframework.test
|-ApiTest.java
|-resources
|-spring.xml
3.2 整合JDBC功能核心类图
DataSource
用于提供Connection
链接操作,后续还会扩展辅助类(ConnectionHandler
、ConnectionHolder
)与数据库事务结合。JdbcTemplate
是执行数据库操作的入口类,提供T execute(StatementCallback<T> action, boolean closeResources)
对数据库操作的实现。JdbcOperations
用于定义很多数据库操作,包括各类的查询处理。这些操作也会调用execute
方法进行处理,再对数据进行封装。- 封装操作就是使用
ResultSetExtractor
接口、RowMapper
接口进行数据类型转换的。
- 封装操作就是使用
3.3 数据源操作
3.3.1 数据源操作抽象类
DataSourceUtils.java
package com.lino.springframework.jdbc.datasource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @description: 数据源操作抽象类
*/
public abstract class DataSourceUtils {
/**
* 获取数据库连接
*
* @param dataSource 数据库对象
* @return 数据库连接
*/
public static Connection getConnection(DataSource dataSource) {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException("Failed to obtain JDBC Connection", e);
}
}
}
DataSourceUtils
数据源的操作工具类提供了连接池的链接、关闭、释放等功能。这也是对 Spring 源码的简化。
3.3.2 JDBC 工具类
JdbcUtils.java
package com.lino.springframework.jdbc.support;
import cn.hutool.core.util.StrUtil;
import java.sql.*;
/**
* @description: JDBC工具类
*/
public class JdbcUtils {
/**
* Determine the column name to use. The column name is determined based on a
* lookup using ResultSetMetaData.
* <p>This method implementation takes into account recent clarifications
* expressed in the JDBC 4.0 specification:
* <p><i>columnLabel - the label for the column specified with the SQL AS clause.
* If the SQL AS clause was not specified, then the label is the name of the column</i>.
*
* @param resultSetMetaData the current meta-data to use
* @param columnIndex the index of the column for the look up
* @return the column name to use
* @throws SQLException in case of lookup failure
*/
public static String lookupColumnName(ResultSetMetaData resultSetMetaData, int columnIndex) throws SQLException {
String name = resultSetMetaData.getColumnLabel(columnIndex);
if (StrUtil.isEmpty(name)) {
name = resultSetMetaData.getColumnName(columnIndex);
}
return name;
}
/**
* Retrieve a JDBC column value from a ResultSet, using the most appropriate
* value type. The returned value should be a detached value object, not having
* any ties to the active ResultSet: in particular, it should not be a Blob or
* Clob object but rather a byte array or String representation, respectively.
* <p>Uses the {@code getObject(index)} method, but includes additional "hacks"
* to get around Oracle 10g returning a non-standard object for its TIMESTAMP
* datatype and a {@code java.sql.Date} for DATE columns leaving out the
* time portion: These columns will explicitly be extracted as standard
* {@code java.sql.Timestamp} object.
*
* @param rs is the ResultSet holding the data
* @param index is the column index
* @return the value object
* @throws SQLException if thrown by the JDBC API
* @see java.sql.Blob
* @see java.sql.Clob
* @see java.sql.Timestamp
*/
public static Object getResultSetValue(ResultSet rs, int index) throws SQLException {
Object obj = rs.getObject(index);
String className = null;
if (null != obj) {
className = obj.getClass().getName();
}
if (obj instanceof Blob) {
Blob blob = (Blob) obj;
obj = blob.getBytes(1, (int) blob.length());
} else if (obj instanceof Clob) {
Clob clob = (Clob) obj;
obj = clob.getSubString(1, (int) clob.length());
} else if ("oracle.sql.TIMESTAMP".equals(className) || "oracle.sql.TIMESTAMPTZ".equals(className)) {
obj = rs.getTimestamp(index);
} else if (null != className && className.startsWith("oracle.sql.DATE")) {
String metadataClassName = rs.getMetaData().getColumnClassName(index);
if ("java.sql.Timestamp".equals(metadataClassName) || "oracle.sql.TIMESTAMP".equals(metadataClassName)) {
obj = rs.getTimestamp(index);
} else {
obj = rs.getDate(index);
}
} else if (obj instanceof Date) {
if ("java.sql.Timestamp".equals(rs.getMetaData().getColumnClassName(index))) {
obj = rs.getDate(index);
}
}
return obj;
}
}
3.4 数据库执行
3.4.1 语句处理器接口
StatementCallback.java
package com.lino.springframework.jdbc.core;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @description: 语句处理器
*/
public interface StatementCallback<T> {
/**
* 执行语句
*
* @param statement 语句对象
* @return 泛型结果
* @throws SQLException SQL异常
*/
T doInStatement(Statement statement) throws SQLException;
}
3.4.2 结果处理器接口
ResultSetExtractor.java
package com.lino.springframework.jdbc.core;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @description: 结果返回器
*/
public interface ResultSetExtractor<T> {
/**
* 返回数据
*
* @param rs 结果集
* @return 泛型结果
* @throws SQLException SQL异常
*/
T extractData(ResultSet rs) throws SQLException;
}
3.4.3 行转列结果处理器实现类
RowMapperResultSetExtractor.java
package com.lino.springframework.jdbc.core;
import cn.hutool.core.lang.Assert;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 行转列
*/
public class RowMapperResultSetExtractor<T> implements ResultSetExtractor<List<T>> {
private final RowMapper<T> rowMapper;
private final int rowsExpected;
public RowMapperResultSetExtractor(RowMapper<T> rowMapper) {
this(rowMapper, 0);
}
public RowMapperResultSetExtractor(RowMapper<T> rowMapper, int rowsExpected) {
Assert.notNull(rowMapper, "RowMapper is required");
this.rowMapper = rowMapper;
this.rowsExpected = rowsExpected;
}
@Override
public List<T> extractData(ResultSet rs) throws SQLException {
List<T> results = this.rowsExpected > 0 ? new ArrayList<>(this.rowsExpected) : new ArrayList<>();
int rowNum = 0;
while (rs.next()) {
results.add(this.rowMapper.mapRow(rs, rowNum++));
}
return results;
}
}
3.4.4 行映射器接口
RowMapper.java
package com.lino.springframework.jdbc.core;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @description: 行映射器接口
*/
public interface RowMapper<T> {
/**
* 返回行记录
*
* @param rs 结果集对象
* @param rowNum 返回的行数
* @return 泛型结果
* @throws SQLException SQL异常
*/
T mapRow(ResultSet rs, int rowNum) throws SQLException;
}
3.4.5 行列Map映射器实现类
ColumnMapRowMapper.java
package com.lino.springframework.jdbc.core;
import com.lino.springframework.jdbc.support.JdbcUtils;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @description: 行列Map映射器
*/
public class ColumnMapRowMapper implements RowMapper<Map<String, Object>> {
@Override
public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
ResultSetMetaData rsMetaData = rs.getMetaData();
int columnCount = rsMetaData.getColumnCount();
Map<String, Object> mapOfColumnValues = createColumnMap(columnCount);
for (int i = 1; i <= columnCount; i++) {
String columnName = JdbcUtils.lookupColumnName(rsMetaData, i);
mapOfColumnValues.putIfAbsent(getColumnKey(columnName), getColumnValue(rs, i));
}
return mapOfColumnValues;
}
protected Map<String, Object> createColumnMap(int columnCount) {
return new LinkedHashMap<>(columnCount);
}
protected String getColumnKey(String columnName) {
return columnName;
}
protected Object getColumnValue(ResultSet rs, int index) throws SQLException {
return JdbcUtils.getResultSetValue(rs, index);
}
}
3.3.6 数据库执行接口
JdbcOperations.java
package com.lino.springframework.jdbc.core;
import java.util.List;
import java.util.Map;
/**
* @description: 数据库执行接口
*/
public interface JdbcOperations {
/**
* 执行语句处理器
*
* @param action 语句处理器
* @param <T> 泛型
* @return 泛型结果
* @throws Exception 异常
*/
<T> T execute(StatementCallback<T> action) throws Exception;
/**
* 执行SQL语句
*
* @param sql SQL语句
*/
void execute(String sql);
/**
* 执行查询
*
* @param sql SQL语句
* @param res 结果返回器
* @param <T> 泛型
* @return 泛型结果
*/
<T> T query(String sql, ResultSetExtractor<T> res);
/**
* 执行查询
*
* @param sql SQL语句
* @param rowMapper 行对象
* @param <T> 泛型
* @return 泛型集合结果
*/
<T> List<T> query(String sql, RowMapper<T> rowMapper);
/**
* 查询列表
*
* @param sql SQL语句
* @return Map集合
*/
List<Map<String, Object>> queryForList(String sql);
}
- 在 Spring JDBC 框架中,
JdbcOperations
的功能很简单,就是定义了一组用于 JDBC 操作的接口。
3.5 数据库操作模板
3.5.1 SQL提供者
SqlProvider.java
package com.lino.springframework.jdbc.core;
/**
* @description: SQL提供者
*/
public interface SqlProvider {
/**
* 获取SQL语句
*
* @return SQL语句
*/
String getSql();
}
3.5.2 JDBC操作抽象类
JdbcAccessor.java
package com.lino.springframework.jdbc.support;
import cn.hutool.core.lang.Assert;
import com.lino.springframework.beans.factory.InitializingBean;
import javax.sql.DataSource;
/**
* @description: JDBC操作接口
*/
public abstract class JdbcAccessor implements InitializingBean {
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
protected DataSource obtainDataSource() {
DataSource dataSource = getDataSource();
Assert.state(dataSource != null, "No DataSource set");
return dataSource;
}
@Override
public void afterPropertiesSet() {
if (getDataSource() == null) {
throw new IllegalArgumentException("Property 'dataSource' is required");
}
}
}
3.5.3 JDBC操作模板
JdbcTemplate.java
package com.lino.springframework.jdbc.core;
import cn.hutool.core.lang.Assert;
import com.lino.springframework.jdbc.datasource.DataSourceUtils;
import com.lino.springframework.jdbc.support.JdbcAccessor;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
/**
* @description: JDBC 操作模板
*/
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
/**
* 查询大小
*/
private int fetchSize = -1;
/**
* 最大行数
*/
private int maxRows = -1;
/**
* 查询时间
*/
private int queryTimeout = -1;
public JdbcTemplate() {
}
public JdbcTemplate(DataSource dataSource) {
setDataSource(dataSource);
afterPropertiesSet();
}
public int getFetchSize() {
return fetchSize;
}
public void setFetchSize(int fetchSize) {
this.fetchSize = fetchSize;
}
public int getMaxRows() {
return maxRows;
}
public void setMaxRows(int maxRows) {
this.maxRows = maxRows;
}
public int getQueryTimeout() {
return queryTimeout;
}
public void setQueryTimeout(int queryTimeout) {
this.queryTimeout = queryTimeout;
}
@Override
public <T> T execute(StatementCallback<T> action) {
Connection con = DataSourceUtils.getConnection(obtainDataSource());
try {
Statement stmt = con.createStatement();
applyStatementSettings(stmt);
return action.doInStatement(stmt);
} catch (SQLException ex) {
throw new RuntimeException("StatementCallback", ex);
}
}
@Override
public void execute(String sql) {
class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
@Override
public String getSql() {
return sql;
}
@Override
public Object doInStatement(Statement statement) throws SQLException {
statement.execute(sql);
return null;
}
}
execute(new ExecuteStatementCallback());
}
@Override
public <T> T query(String sql, ResultSetExtractor<T> res) {
class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
@Override
public String getSql() {
return sql;
}
@Override
public T doInStatement(Statement statement) throws SQLException {
ResultSet rs = statement.executeQuery(sql);
return res.extractData(rs);
}
}
return execute(new QueryStatementCallback());
}
@Override
public <T> List<T> query(String sql, RowMapper<T> rowMapper) {
return result(query(sql, new RowMapperResultSetExtractor<>(rowMapper)));
}
@Override
public List<Map<String, Object>> queryForList(String sql) {
return query(sql, new ColumnMapRowMapper());
}
private static <T> T result(T result) {
Assert.state(null != result, "No result");
return result;
}
protected void applyStatementSettings(Statement stat) throws SQLException {
int fetchSize = getFetchSize();
if (fetchSize != -1) {
stat.setFetchSize(fetchSize);
}
int maxRows = getMaxRows();
if (maxRows != -1) {
stat.setMaxRows(maxRows);
}
}
}
JdbcTemplate
是对数据库操作的封装,在启动时由外部传入DataSource
数据源,这也是处理数据库操作最基本的方法。- 通过这样的封装,减少了用户操作的复杂性,也符合设计模式的原则。
execute
方法是整个数据库操作的核心方法,将同类的数据操作进行统一封装。一些个性化的操作需要进行回调处理。- 例如:在
JdbcTemplate#query
方法中,也是对JdbcTemplate#execute
进行包装操作,并返回处理结果。
- 例如:在
四、测试:JDBC功能整合
4.1 添加测试配置
4.1.1 sql数据库表
user.sql
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`userId` varchar(9) DEFAULT NULL COMMENT '用户ID',
`userHead` varchar(16) DEFAULT NULL COMMENT '用户头像',
`createTime` datetime DEFAULT NULL COMMENT '创建时间',
`updateTime` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
4.1.2 Spring属性配置文件
spring.xml
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring?useSSL=false&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="jdbcTemplate" class="com.lino.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
- 在
spring.xml
配置文件中,先配置数据库的链接信息及库表,再将dataSource
注入JdbcTemplate
中,由JdbcTemplate
完成数据库的操作。
4.1.3 初始化 Spring和JdbcTemplate对象
ApiTest.java
package com.lino.springframework.test;
import com.lino.springframework.context.support.ClassPathXmlApplicationContext;
import com.lino.springframework.jdbc.core.JdbcTemplate;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import java.util.Map;
/**
* @description: 测试类
*/
public class ApiTest {
private JdbcTemplate jdbcTemplate;
@Before
public void init() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
jdbcTemplate = applicationContext.getBean(JdbcTemplate.class);
}
}
4.2 单元测试
4.2.1 插入测试
ApiTest.java
@Test
public void execute() {
jdbcTemplate.execute("insert into user (id, userId, userHead, createTime, updateTime) values (1, '123456789', '01-50', now(), now())");
}
测试结果
信息: {dataSource-1} inited
4.2.2 查询测试
ApiTest.java
@Test
public void queryForList() {
List<Map<String, Object>> allResult = jdbcTemplate.queryForList("select * from user");
for (Map<String, Object> objectMap : allResult) {
System.out.println("测试结果:" + objectMap);
}
}
测试结果
信息: {dataSource-1} inited
测试结果:{id=1, userId=123456789, userHead=01-50, createTime=2022-12-08 14:39:15.0, updateTime=2022-12-08 14:39:15.0}
- 从测试结果看,这里已经把操作数据库的
JdbcTemplate
交由 Spring Bean 容器管理,并验证其数据库操作。
五、总结:JDBC功能整合
- 本节主要介绍了 Spring Bean 容器的扩展功能,可以在指定的任何阶段把需要交给 Spring 管理的对象进行初始化。
- 如:
InitializingBean
可以在BeanFactory
设置属性后进行相应的处理,整合其他对象。
- 如:
- 另外,需要熟悉 JDBC 的包装,使用支撑层
support
承接Bean
对象的扩展。DataSource
提供了操作数据源的功能,在core
包中完成对数据库的操作并返回相应的结果。