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

相关文章

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows