DataSource超高级应用——对DataSource的合理封装

【数据库连接池】c3p0-druid-SpringJDBC 数据库连接池 概念: 其实就是一个容器(集合),存放数据库连接的容器。 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。 好处: 1. 节约资源 2. 用户访问高效 实现: 标准接口:DataSource javax.sql包下的 方法: 获取连接:getConnection() 归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Con 阅读详情
  
转自:cnjbb论坛的jdbc专栏的axman大侠写的-DataSource超高级应用
链接:
http://www.cnjbb.org/thread.jsp?boardid=23&threadid=34286


    在前面的介绍中,我们可以看出, DataSource才能提供最高性能的对数据库的并发访问,
但是,对DataSource的引用,也还有很多知识要弄清楚,获取Connection的方式是数据库性能最相
关的技术,而对DataSource的调用对数据库性能起着很大的决定作用。
    一般对于DataSource的引用是通过以下流程来进行:
            Context ct = new InitialContext();
            DataSource ds = (DataSource) ct.lookup(sourceUrl);
    就这么简单的两行,但其调用条件不同却可以产生性能上巨大的差别。因为一个取得
Connect的封装类(Bean)要对DataSource的引用,会有着多种方式。如果是作为一个普通的封
装类,我们可以在构造方法中调用,而作为javaBean可以在init方法中调用,但无论要哪儿调用,
当我们对这个类或Bean进行调用时,都要对DataSource进行查找。其实DataSource的查找过程也
是一个相当消耗资源的过程,所以我们应该把DataSource声明为静态资源,因为即使你对封装类
或Bean中每次调用都进行一次查找,事实上你得到的DataSource还是那个不变的唯一的资源。那
么为什么不把它声明为static呢?这样只在需要的时候才去查找,而更多的时候就可以直接对已
经查找到的DataSource进行直接引用:

public class ConnectionFactory{
    private static DataSource dsCache = null;

    aMethodForGetConnectio(){
        if(dsCache == null){
            synchronized(this){
                if(dsCache==null){
                    Context ct = new InitialContext();
                    dsCache = (DataSource) ct.lookup(source);
                }
            }
        }
        Connection conn = dsCache.getConnection();
    }
}
我们看到,一般情况下,只有当第一次调用ConnectionFactory时才会对DataSource进行查找,而
其它时候只要不发生意外(目前我还想不出有什么情况会使原来不是null的DataSource突然null)
就不再需要查找而直接引用了.而如果你不把DataSource声明为静态的,那么每次对调用
ConnectionFactory都要产生一次jndi的查找:
public class ConnectionFactory{
    private DataSource dsCache = null;

    aMethodForGetConnectio(){
        if(dsCache == null){
            Context ct = new InitialContext();
            dsCache = (DataSource) ct.lookup(source);
        }
        Connection conn = dsCache.getConnection();
    }
}
因为dsCache不是静态资源,所以每次调用,if(dsCache==null)都成立.
有人说那Connection如果也是静态的那不也节省资源了吗?注意Connection不是工场,如果多个用
户同时对同一Connection访问,那么任何人都不能关闭Connection,而最后变成谁也没有关闭
Connection,因为最后一次使用的用户根本不知道后面到底是否有人要使用.另一方面,一个
Connection处理能力很低,不可能同时满足很多用户同时对数据库存取数据.而DataSource虽然是
多个用户对同一资源的引用,但它是工厂,不同用户访问同一DataSource得到的是不同的Connection
资源.

为了对特定DataSource进行查找,我们要对jndi的引用进行配置,一般来说,如果一个封装类或Bean
不可能将jndi引用字符串写死要代码中,可以放在配置文件中然后读取:
    Properties properties = new Properties();
    properties.load(new FileInputStream("配置文件"));
    dsCache = (DataSource) ct.lookup(properties.getProperty("key"));
这样在我们要修改DataSource时就可以难过修改"配置文件"而不要重新编译ConnectionFactory,但
是如果是对一个容器下的多个应用同时配置了多个DataSource,我们根本无法指定到底查打哪个数据
源,所以最好能重载一个方法,无论是构造方法还是其它方法都应该重载一个根据参数查找的方法:
public class ConnectionFactory{
    private static DataSource dsCache = null;

    aMethodForGetConnectio(){
        if(dsCache == null){
            synchronized(this){
                if(dsCache==null){
                    Properties properties = new Properties();
                    properties.load(new FileInputStream("配置文件"));
                    Context ct = new InitialContext();
                    dsCache = (DataSource) ct.lookup(properties.getProperty("key"));
                }
            }
        }
        Connection conn = dsCache.getConnection();
    }
    aMethodForGetConnectio(String source){
        if(dsCache == null){
            synchronized(this){
                if(dsCache==null){
                    Context ct = new InitialContext();
                    dsCache = (DataSource) ct.lookup(source);
                }
            }
        }
        Connection conn = dsCache.getConnection();
    }

}

另外对于默认的查找字符串,我们仍然可以做进一步的优化,不过即使每次读取属性,性能也没有太大的影响:
public class ConnectionFactory{
    private static DataSource dsCache = null;
    private static Properties properties = new Properties();
    aMethodForGetConnectio(){
        if(dsCache == null){
            synchronized(this){
                if(dsCache==null){
                    if(!properties.containsKey("key"))
                        properties.load(new FileInputStream("配置文件"));
                    //只有在没有找到属性时才去再读配置文件
                    Context ct = new InitialContext();
                    dsCache = (DataSource) ct.lookup(properties.getProperty("key"));
                }
            }
        }
        Connection conn = dsCache.getConnection();
    }
}
通过以上优化,可以使你的封装类以最低的资源消耗来获取最大的性能.我们可以这样来进行测试:
把if(dsCache == null){}发生时的情况记录到日志中,看看什么时候发生了这种异常,我对我的数据库进行了跟踪,我们给青岛日报社做的一台邮件系统主机上有6万多用户,同时并发的访问量很大,但日记记录,只有每次重启动应用的时候才产生一条记录,也就是ConnectionFactory第一次调用时才产生日志,其它情况非常正常:
public class ConnectionFactory{
    private static DataSource dsCache = null;
    private static Properties properties = new Properties();
    aMethodForGetConnectio(){
        if(dsCache == null){
            synchronized(this){
                if(dsCache==null){
                    if(!properties.containsKey("key"))
                        properties.load(new FileInputStream("配置文件"));
                    //只有在没有找到属性时才去再读配置文件
                    Context ct = new InitialContext();
                    dsCache = (DataSource) ct.lookup(properties.getProperty("key"));
                }
            }
            //当发生dsCache == null时,记录下发生对该方法的调用者:
            PrintWriter pw = new PrintWriter(new FileWriter("connection.log",true));
            pw.println(new java.util.Date() + ":当前方法名如aMethodForGetConnectio():"
                    + sun.reflect.Reflection.getCallerClass(2));
            pw.close();
        }
        Connection conn = dsCache.getConnection();
    }
}
主要记录当前日期,当前方法名称和是哪个类调用了该方法.sun.reflect.Reflection.getCallerClass(int i)方法中,i为0是Reflection本身,1是Bean或封装类,就是ConnectionFactory,2就是调用它的类,3以上不确定.这样你可以把你的封装类或Bean进行一段时间(至少几天以上)跟踪,如果应用一直没有重启动,那就应该只产生一条记录.这样你就有了一个顶级性能的封装类了.
深入解析dynamic-datasource:多数据源路由原理与事务管理实战 在Java企业级应用开发中,多数据源管理是应对读写分离、分库分表等场景的核心技术。其原理基于Spring框架的AbstractRoutingDataSource,通过线程上下文(ThreadLocal)存储数据源标识,结合AOP切面在方法执行前动态切换数据源键,实现透明化的数据访问路由。这一机制的技术价值在于解耦业务逻辑与具体数据源,提升系统扩展性和维护性,广泛应用于微服务架构下的数据库水平拆分、多租户数据隔离等场景。然而,在与Spring声明式事务(@Transactional)协作时,需特别注意切面执行 阅读详情

相关推荐

深入解析dynamic-datasource-spring-boot-starter源码:多数据源动态路由与事务协同

在构建现代企业级应用时,多数据源管理是应对业务拆分、读写分离等复杂场景的关键技术。其核心原理在于通过动态路由机制,将数据访问请求透明地分发到不同的数据库实例。这项技术的核心价值在于实现了数据访问层的解耦与灵活扩展,同时保持对业务代码的低侵入性。典型的应用场景包括微服务架构下的数据隔离、读写分离负载均衡以及多租户SaaS平台的数据分区。本文聚焦于dynamic-datasource-spring-boot-starter这一流行开源组件,深入剖析其基于ThreadLocal的上下文传递机制和与Spring事务

weixin_30326515的博客 441

DataSource

1、基础概念 1.1、DriverManager DriverManager(驱动管理器)是由SUN公司实现的,提供了基本的获取连接方式。主要作用是管理注册到DriverManager中的JDBC驱动程序,并根据需要使用JDBC驱动程序建立与数据服务器的连接网络。频繁的进行数据库连接会产生很大的开销。 1.2、DataSource DataSouce(数据源)指定的用于获取数据库连接的规范接口。它存在于javax.sql包中,用来替代DriverManager的方式来...

better_zhang的博客 1871

高效可复用的UITableView封装实践

在现代iOS应用开发中,作为最核心的UI组件之一,承载着大量数据展示需求。而真正决定表格视觉表现力与交互体验的关键,在于其单元格——的设计质量。一个优秀的自定义Cell不仅需要满足功能完整性和界面美观性,更应在架构层面具备良好的可维护性、扩展性与性能表现。本章节将系统性地探讨如何从零构建高质量的自定义,涵盖创建方式选型、动态布局适配、数据绑定机制、事件传递模式以及性能优化策略等多个维度。

weixin_36184718的博客 809

datasource的封装和监控

1.dispatcher-master.xml <?xml version="1.0" encoding="utf-8"?> <config> <value>{"name":"dispatcher","driverClassName":"com.mysql.jdbc.Driver", "jdbcUrl":"jdbc:mysql://mysql-m-wr-car-all-test-db.01zhuanche.com:3306/dispatcher?zeroDat

八荒六合唯我独尊 451

从零开始学习信号完整性(SIPI)--1 简介

信号完整性就是研究如何让驱动芯片发出的信号经过传输通道被接收芯片正确接收的学问。 信号完整性包含了三个要素: 信号:是被传输的主体,我们首先要了解、熟悉信号的特性。 芯片:分为驱动芯片和接收芯片,信号完整性工程师就是要实现信号在驱动芯片和接收芯片之间的正确传输。 传输通道:是传输信号的介质,是信号所走的“路”。如何实现信号的正确传输呢?那就要信号完整性工程师为信号“修路”、“搭桥”。

qq_29476769的博客 4万+

jetson nano网络配置(有线、无线、USB)

注意:本节内容使用Jetson nano B01 版本或Jetson nano ALT 版本安装方式相同,在安装无线网卡等设备时,由于线材和设备比较脆弱,需要轻拿轻放,接口连接不上时,需要重新对准接口在进行连接,不要强行连接。Jetson nano 需要连接网络来进行更多的操作,本节就来讲解Jetson nano 的三种网络连接方法。有线:我们可以使用网线连接Jetson nano 的RJ45 接口,实现联网。

m0_73841621的博客 1万+

数据库配置文件properties中用户名、密码加密处理

项目中一般都会有数据库配置文件properties,其中用户名和密码一般都是明文存储,这样很不安全,下面介绍几种对用户名和密码进行加密处理的方法 一、PropertyPlaceholderConfigurer 重写PropertyPlaceholderConfigurer类,覆盖里面的convertProperty方法,对加密的用户名和密码进行解密处理并返回 替换xml配置文件中的org.s...

飞龙在天 7248

GIS坐标系转换以及空间校正和地理配准

许多小伙伴都对坐标系,投影这类问题迷迷糊糊,我之前也一样,现在总结一下。 坐标系的转换1.为什么要进行坐标系的转换?2. 不同坐标系的介绍1.地理坐标系我国常见的地理坐标(1).北京54坐标系(2).西安80坐标系(3).WGS-84坐标系(4).大地2000坐标系2.投影坐标系我国常用的投影坐标系(1) UTM投影(2) 高斯-克吕格投影(3) 兰伯特投影(4) 阿尔伯斯投影投影坐标系的选择3. 坐标系的转换1.已知坐标系之间的转换1.1 两坐标系的参考椭球相同1.2 两坐标系的参考椭球不一致,但是GIS

m0_47258611的博客 8913

理解封装/抽象------基础封装/抽象和回调封装/抽象

先看看基础封装/抽象: #include using namespace std; int add(int x, int y) { return x + y; } // 对add进行基础封装 int add3(int x, int y, int z) { return x + add(y, z); } int main() { cout << add3(1, 2, 3) << en

认知 行动 坚持 7421

事件相机数据处理实战:从原始事件流到视觉表征的三种核心方法

本文深入探讨了事件相机数据处理的核心环节,即如何将异步、稀疏的原始事件流转换为深度学习模型可处理的视觉表征。文章重点解析了三种核心方法:逐通道累积、体素网格双线性插值和对称累积事件表示,详细阐述了其原理、代码实现、可视化效果及各自的适用场景,为事件相机在目标识别、光流估计等视觉任务中的高效应用提供了实战指南。

read5的博客 438

SAP ABAP实战:手把手教你用BAPI_BILLINGDOC_CREATEMULTIPLE批量开票(附完整代码与避坑指南)

本文详细解析了SAP ABAP中BAPI_BILLINGDOC_CREATEMULTIPLE批量开票的全流程,包括参数配置、事务控制、错误处理及性能优化。通过实战案例和完整代码示例,帮助开发者高效处理大批量发票生成任务,避免常见陷阱,提升开发效率。

weixin_34101914的博客 265

DataSource高级应用

 在前面的介绍中,我们可以看出, DataSource才能提供最高性能的对数据库的并发访问,但是,对DataSource的引用,也还有很多知识要弄清楚,获取Connection的方式是数据库性能最相关的技术,而对DataSource的调用对数据库性能起着很大的决定作用。    一般对于DataSource的引用是通过以下流程来进行:            Context ct = new Init

张凡的专栏 641

Lumerical官方案例、FDTD时域有限差分法仿真学习(三)——环形谐振器(Ring resonator)之第二&第三部分

二、使用 MODE 的参数提取和蒙特卡罗 三、最终参数提取

weixin_45719141的博客 1万+

【转】DataSource高级应用

我们知道 DataSource能提供最高性能的对数据库的并发访问,但是,对DataSource的引用,也还有很多知识要弄清楚,获取Connection的方式是数据库性能最相关的技术,而对DataSource的调用对数据库性能起着很大的决定作用。    一般对于DataSource的引用是通过以下流程来进行: Context ct = new InitialContext(); Data...

weixin_33816821的博客 115

【原理图PCB专题】Cadence17.4 PCB位号重排与反标

Cadence17.4 PCB位号重排与反标比Cadence16版本更简单一些,那到底如何操作?

一点硬件 1181

Qt Installer Framework 简单使用

qt installer framework 简单使用

qq_42815643的博客 2575

Recyclical DataSource深度指南:高效数据管理与Diffing优化技巧

Recyclical是一个基于Kotlin DSL的RecyclerView库,提供了简洁易用且可扩展的数据管理解决方案。本文将深入探讨Recyclical的DataSource组件,分享高效数据管理与Diffing优化的实用技巧,帮助开发者构建流畅的列表体验。 ## 什么是DataSource?核心功能解析 DataSource是Recyclical架构中的核心数据管理层,负责为Recycl

gitblog_01176的博客 465

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Spring DataSource核心原理与生产实践指南

数据库连接池作为Java企业级应用的基础组件,其核心作用是通过连接复用提升系统性能与稳定性。从技术原理看,连接池通过维护活跃连接集合、心跳检测等机制,有效解决了频繁创建/销毁连接的性能损耗问题。Spring框架通过DataSource接口的标准化封装,集成了HikariCP等主流连接池实现,并扩展出多数据源路由、分布式事务支持等企业级特性。在实际工程中,合理的连接池配置(如maximumPoolSize、leakDetectionThreshold等参数)对系统稳定性至关重要,特别是在高并发场景下,不当配置

weixin_30666401的博客 428

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

dynamic-datasource注解优先级:方法级注解的终极指南

dynamic-datasource是Spring Boot生态中一个强大的动态数据源切换框架,它通过简洁的注解机制实现了多数据源的无缝切换。在复杂的业务场景中,理解@DS注解的优先级规则至关重要,特别是方法级注解如何优先于类级注解,这能帮助你构建更加灵活和可维护的数据访问层。 ## 什么是dynamic-datasource注解优先级? dynamic-datasource框架采用**就近原

gitblog_00666的博客 464

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Dynamic-Datasource配置校验:嵌套对象完整指南

在Spring Boot多数据源应用中,嵌套对象的配置校验是确保数据源正确初始化的关键环节。dynamic-datasource作为一款强大的动态数据源管理框架,提供了完善的配置校验机制,帮助开发者避免配置错误导致的应用启动失败问题。 ## 什么是嵌套对象配置校验? 嵌套对象配置校验是指对dynamic-datasource中复杂的数据源配置对象进行验证的过程。这些配置可能包含多层次的属性设置

gitblog_00724的博客 664

一个架构合理的UITableView应该是如何的?

原文: http://www.chentoo.com/?p=200  iOS 开发中,UITableView 应该是最经常使用到的了。完毕一个UITableView应该实现他的DataSource和Delegate来讲数据Model填充进View(Cell)中。大家也是知晓的。可是一个UITableView应该如何才干实现良好的架构,事实上非常多人是不在意的。而这也是一个刚開始学...

weixin_34191734的博客 123

dynamic-datasource数据源工厂:单例模式的终极实现指南

在现代企业级应用中,**dynamic-datasource动态数据源**框架通过巧妙运用单例模式,为Spring Boot应用提供了高效、稳定的多数据源管理解决方案。这个强大的工具让开发者能够轻松实现主从分离、读写分离等复杂的数据源场景,大大提升了系统的可扩展性和性能表现。 ## 🔍 什么是单例模式在数据源管理中的重要性 单例模式确保在整个应用生命周期中,每个数据源实例只被创建一次,这带来

gitblog_00436的博客 609
上一篇: 通过JDBC访问Oracle的Lob类型的方法(来自武汉白云黄鹤站)
下一篇: JDBC的高级应用一 ——关于数据库连结
dacula
博客等级 码龄24年 6粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值