Spring源代码分析(11)---JDBC Dao(老树发新芽)

2024-04-27 11:18

本文主要是介绍Spring源代码分析(11)---JDBC Dao(老树发新芽),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在数据库访问技术中,我们有很多选择,诸如jpa,hibernate但是无论选择那种,其实,我们都无法拒绝使用JDBC,Spring为集成JDBC做个很多工作,让我们来看下,这最底层数据库访问技术在春天老树发新芽;

实现,我们来看先,我们如何使用SPRING JDBC的配置和使用:

ApplicationContext.xml:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans
  3.     xmlns="http://www.springframework.org/schema/beans"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  6. <!--数据源的配置-->   
  7. <bean id="dataSource"
  8.         class="org.apache.commons.dbcp.BasicDataSource">
  9.         <property name="driverClassName"
  10.             value="com.mysql.jdbc.Driver">
  11.         </property>
  12.         <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"></property>
  13.         <property name="username" value="root"></property>
  14.     </bean>
  15.     <bean id="sessionFactory"
  16.         class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  17.         <property name="dataSource">
  18.             <ref bean="dataSource"></ref>
  19.         </property>
  20.         <property name="hibernateProperties">
  21.             <props>
  22.                 <prop key="hibernate.dialect">
  23.                     org.hibernate.dialect.MySQLDialect
  24.                 </prop>
  25.             </props>
  26.         </property>
  27.     </bean>
  28.    <!--Dao的配置-->
  29.     <bean id="dao" name="dao" class="org.corey.dao.CoreyDao"
  30.         dependency-check="default">
  31.         <property name="dataSource">
  32.             <ref bean="dataSource"></ref>
  33.         </property>
  34.     </bean></beans>
测试:
  1. package org.corey.demo;
  2. import org.corey.dao.CoreyDao;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. import org.springframework.jdbc.core.JdbcTemplate;
  6. public class Demo {
  7.     public static void main(String[] args) {
  8.         ApplicationContext context = new ClassPathXmlApplicationContext(
  9.                 "applicationContext.xml");
  10.         CoreyDao dao = (CoreyDao)context.getBean("dao");
  11.         JdbcTemplate template=dao.getJdbcTemplate();
  12.         template.execute("insert into customer(name) values('corey')");
  13.         
  14.     }
  15. }
下面,我们来详细的分析一下Spring Dao的代码结构:


其实,在这里,有很大的感觉让我们有桥接模式的影子,但是这里我们首先要注意,在JDbcDaoSupport并没有依赖于一个抽象的Template接口,一方面是因为在Sprin构建过程中,DaoSupport与Template之间是一对一的关系,JdbcDaoSupport就只能对应JdbcTemplate,所以,不会出现Template的动态切换,所以这里并没有依赖抽象编程;
在程序中,任何功能方法,都是由接口定义实现的,所以我们可以看见,简单的JdbcTemplate的数据库访问功能的实现是由JdbcAccessor定义实现,与数据库的交互动作是由JdbcOperations定义的;

而JdbcTemplate与DataSource的依赖是基于抽象和接口的,这是因为系统所采用的连接池本身就是一个变化点,在这里,我们是而已实现用户选择定制的,所以,这里,我们更多的是采用了把组合聚合原则实现;

分析完基本结构以后,我们再来看一下功能代码的实现:

Dao:
  1. public abstract class DaoSupport implements InitializingBean {
  2.     /** Logger available to subclasses */
  3.     protected final Log logger = LogFactory.getLog(getClass());
  4.         
  5.         //在访问器注入以后执行的初始化方法,运用了模板模式;
  6.     public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
  7.         themselves.
  8.         try {
  9.             initDao();
  10.         }
  11.         catch (Exception ex) {
  12.             throw new BeanInitializationException("Initialization of DAO failed: " + ex.getMessage(), ex);
  13.         }
  14.     }
  15.     //模板模式的一个抽象方法;
  16.     protected abstract void checkDaoConfig() throws IllegalArgumentException;
  17.     //初始化Dao,这是模板模式的一个钩子;
  18.     protected void initDao() throws Exception {
  19.     }
  20. }

  1. package org.springframework.jdbc.core.support;
  2. import java.sql.Connection;
  3. import javax.sql.DataSource;
  4. import org.springframework.dao.support.DaoSupport;
  5. import org.springframework.jdbc.CannotGetJdbcConnectionException;
  6. import org.springframework.jdbc.core.JdbcTemplate;
  7. import org.springframework.jdbc.datasource.DataSourceUtils;
  8. import org.springframework.jdbc.support.SQLExceptionTranslator;

  9. public abstract class JdbcDaoSupport extends DaoSupport {
  10.     private JdbcTemplate jdbcTemplate;
  11.     //让注入数据源的时候,自动构造出一个模板属性;
  12.         //在此方法之后,会Dao的检查和自定义初始化;
  13.     public final void setDataSource(DataSource dataSource) {
  14.       this.jdbcTemplate = createJdbcTemplate(dataSource);
  15.        initTemplateConfig();//扩展点;
  16.     }
  17.     //通过注入的数据源,构造出模板
  18.     protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {
  19.         return new JdbcTemplate(dataSource);
  20.     }
  21.     /**
  22.      * Return the JDBC DataSource used by this DAO.
  23.      */
  24.     public final DataSource getDataSource() {
  25.         return (this.jdbcTemplate != null ? this.jdbcTemplate.getDataSource() : null);
  26.     }
  27.     //注入模板
  28.     public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  29.         this.jdbcTemplate = jdbcTemplate;
  30.        initTemplateConfig();//扩展点;
  31.     }
  32.     //得到模板;
  33.     public final JdbcTemplate getJdbcTemplate() {
  34.       return jdbcTemplate;
  35.     }
  36.         
  37.         //判断你时候注入了一个模板或者数据源,如果没有,那么抛出异常
  38.     protected final void checkDaoConfig() {
  39.         if (this.jdbcTemplate == null) {
  40.             throw new IllegalArgumentException("dataSource or jdbcTemplate is required");
  41.         }
  42.     }
  43.     //获取连接;
  44.     protected final Connection getConnection() throws CannotGetJdbcConnectionException {
  45.         return DataSourceUtils.getConnection(getDataSource());
  46.     }
  47.         
  48.         //异常转换;
  49.     protected final SQLExceptionTranslator getExceptionTranslator() {
  50.         return this.jdbcTemplate.getExceptionTranslator();
  51.     }
  52.     //关闭连接;
  53.     protected final void closeConnectionIfNecessary(Connection con) {
  54.         releaseConnection(con);
  55.     }
  56.           
  57.         //释放连接;
  58.     protected final void releaseConnection(Connection con) {
  59.         DataSourceUtils.releaseConnection(con, getDataSource());
  60.     }
  61. }
通过这个方式,我们可见系统给我们保留一个扩展的接口,我们在 initDao()方法中能够自定义的进行扩展,在后面,我们会看到具体的实例;

接下来,我们来分析一下JdbcTemplate:
JdbcAccessor利用DataSource来实现数据库的访问,通过DataSource出取得连接,用Spring对连接进行管理,然后,利用这个连接实现curd功能;


我们来看下一个扩展好的功能更强大的NamedParameterJdbcDaoSupport;

  1. public class NamedParameterJdbcDaoSupport extends JdbcDaoSupport {
  2.     
  3.     private NamedParameterJdbcTemplate namedParameterJdbcTemplate;


  4.     //自定义扩展代码
  5.         //将一个普通的模板包装成为一个可命名参数的模板
  6.     protected void initTemplateConfig() {
  7.         this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate());
  8.     }

  9.     //获得改良后的模板;
  10.     public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
  11.       return namedParameterJdbcTemplate;
  12.     }

  13. }
之所以没有抽象出Template接口,在这里也有了良好的体现,我们并不是在JdbcDaoSupport中动态的切换了JdbcTemplate类,而是先生成了一个NamedParameterJdbcDaoSupport类,因为JdbcTemplate无法和NamedParameterJdbcTemplate无法用的方法没有办法共享一个接口来定义(参数和功能不同);
在由JdbcTemplate到NamedParameterJdbcTemplate的过程中间,我们发现功能在其基础上强大了,但是功能还是采用委托的机制实现,我们知道在设计模式中间,动态改变方法的模式有大名鼎鼎的三种
1):装饰模式;
2) :代理模式;
3):适配器模式;
由于前两种模式暴露出的接口都是不变的,而适配器模式就正式现在所急需的;




该模板提供参数映射,能够从Bean属性或者Map中得到相应的参数的名字:

这篇关于Spring源代码分析(11)---JDBC Dao(老树发新芽)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/940356

相关文章

springboot健康检查监控全过程

《springboot健康检查监控全过程》文章介绍了SpringBoot如何使用Actuator和Micrometer进行健康检查和监控,通过配置和自定义健康指示器,开发者可以实时监控应用组件的状态,... 目录1. 引言重要性2. 配置Spring Boot ActuatorSpring Boot Act

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

java如何分布式锁实现和选型

《java如何分布式锁实现和选型》文章介绍了分布式锁的重要性以及在分布式系统中常见的问题和需求,它详细阐述了如何使用分布式锁来确保数据的一致性和系统的高可用性,文章还提供了基于数据库、Redis和Zo... 目录引言:分布式锁的重要性与分布式系统中的常见问题和需求分布式锁的重要性分布式系统中常见的问题和需求

SpringBoot基于MyBatis-Plus实现Lambda Query查询的示例代码

《SpringBoot基于MyBatis-Plus实现LambdaQuery查询的示例代码》MyBatis-Plus是MyBatis的增强工具,简化了数据库操作,并提高了开发效率,它提供了多种查询方... 目录引言基础环境配置依赖配置(Maven)application.yml 配置表结构设计demo_st

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.