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

相关文章

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

Java利用docx4j+Freemarker生成word文档

《Java利用docx4j+Freemarker生成word文档》这篇文章主要为大家详细介绍了Java如何利用docx4j+Freemarker生成word文档,文中的示例代码讲解详细,感兴趣的小伙伴... 目录技术方案maven依赖创建模板文件实现代码技术方案Java 1.8 + docx4j + Fr

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

基于SpringBoot+Mybatis实现Mysql分表

《基于SpringBoot+Mybatis实现Mysql分表》这篇文章主要为大家详细介绍了基于SpringBoot+Mybatis实现Mysql分表的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录基本思路定义注解创建ThreadLocal创建拦截器业务处理基本思路1.根据创建时间字段按年进

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态