我们知道 DataSource能提供最高性能的对数据库的并发访问,
但是,对DataSource的引用,也还有很多知识要弄清楚,获取Connection的方式是数据库性能最相
关的技术,而对DataSource的调用对数据库性能起着很大的决定作用。
一般对于DataSource的引用是通过以下流程来进行:
- Context ct = new InitialContext();
- DataSource ds = (DataSource) ct.lookup(sourceUrl);
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{
- 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();
- }
- }
public class ConnectionFactory{
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{
- DataSource dsCache = null;
-
- aMethodForGetConnectio(){
- if(dsCache == null){
- Context ct = new InitialContext();
- dsCache = (DataSource) ct.lookup(source);
- }
- Connection conn = dsCache.getConnection();
- }
- }
public class ConnectionFactory{
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"));
Properties properties = new Properties();
properties.load(new FileInputStream("配置文件"));
dsCache = (DataSource) ct.lookup(properties.getProperty("key"));
这样在我们要修改DataSource时就可以难过修改"配置文件"而不要重新编译ConnectionFactory,但
是如果是对一个容器下的多个应用同时配置了多个DataSource,我们根本无法指定到底查打哪个数据
源,所以最好能重载一个方法,无论是构造方法还是其它方法都应该重载一个根据参数查找的方法:
- public class ConnectionFactory{
- 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{
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{
- static DataSource dsCache = null;
- 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();
- }
- }
public class ConnectionFactory{
static DataSource dsCache = null;
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{
- static DataSource dsCache = null;
- 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"));
- }
- }
-
- 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();
- }
- }
public class ConnectionFactory{
static DataSource dsCache = null;
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进行一段时间(至少几天以上)跟踪,如果应用一直没有重启动,那就应该只产生一条
记录.这样你就有了一个顶级性能的封装类了
分享到:
相关推荐
Java 应用程序执行。教程中的示例代码是为 DB2 通用数据库 7.2 编写的,但因为使用了 DataSource 对象, 修改这些代码以适用于其它数据库是不成问题的。 本教程假定您已经熟悉 Java 编程语言,而且在一定程度...
深入探讨DataSource的应用 第6章 ASP.NET 2.0登录与身份验证机制 第7章 ProFile范例——制作用户配置文件 第8章 MasterPage范例——使用母版页 第9章 Theme与Skin范例 第10章 WebParts范例 第11章...
深入探讨DataSource的应用 第6章 ASP.NET 2.0登录与身份验证机制 第7章 ProFile范例——制作用户配置文件 第8章 MasterPage范例——使用母版页 第9章 Theme与Skin范例 第10章 WebParts范例 第11章...
安装通过maven,只需克隆并通过mvn clean install创建项目,并将其添加到您的项目依赖项中用法该应用程序的主要API是DataSource和PersistenceProvider 。 您通过通过DataSource类向PersistenceProvider提供信息来...
在Spring Boot中,可以使用配置文件来管理应用程序的配置。这些配置文件可以根据不同的环境进行分离和管理,Spring...Spring Boot还提供了更多高级的配置方式,如使用@Profile注解、条件注解等来实现更精细的配置管理。
除了具有高级组件,无以比拟JDK,平台和IDE支持,1年高水准的技术支持加上免费升级,JClass DesktopViews 还包括了专业Java开发者建立接口丰富的客户端应用程序所需的任何功能。 组件列表 JClass Chart 为GUI提供...
在VC 6.0程序中执行数据库事务的一个范例,是一个数据库的高级应用例子,关于设置ADO控件,方法如下: (1)在程序中选择ResourceView视图,打开“Dialog”节点下的“IDD_AFFAIR_DIALOG”对话框资源,右键单击ADO ...
该应用程序运行在 功能性 建立专案 建立成员 显示与项目关联的成员 显示项目成员是其中的一部分 在项目中添加和删除成员 编辑和删除成员和项目 设计说明 乔纳森·普斯帕拉贾(Jonathan Pusparajah)和安德烈亚斯·...
10.5.1 DataSource 和 JDBCTemplate开发 227 10.5.2 Hibernate 整合 Spring开发 236 10.5.2.1 创建项目,添加必要的开发功能 236 10.5.2.2 反向工程生成Spring整合Hibernate的DAO 238 10.5.2.3 用Spring 1.2 的事务...
使用DataSource属性,可从数据库或数组中读取图表。内部的过滤让可提供的数据模式于所需绘制的图表选择类型相匹配。更可让开发者在图表绘制中调整行和列的包含/非包含的情况。 强大的美学增强— 图表不仅仅...
1.2 高级语言 1.2.1 结构化查询语言 1.2.2 数据定义语言 1.2.3 数据处理语言 1.2.4 数据查询语言 1.3 事务管理和事务控制命令 1.3.1 ACID测试 1.3.2 SQL中的事务管理 1.4 数据库安全和数据控制语言 1.4.1 ...
使用DataSource属性,可从数据库或数组中读取图表。内部的过滤让可提供的数据模式于所需绘制的图表选择类型相匹配。更可让开发者在图表绘制中调整行和列的包含/非包含的情况。 高级安全性 UltraWebChart提供了一...
*第六阶段:JDBC深入理解高级特性:包括数据库连接池,存储过程,触发器,CRM思想; *第七阶段:HTML语言学习,包括HTML标签,表单标签以及CSS,这是Web应用开发的基础; *第八阶段:JavaScript脚本语言,包括...
高级主题 II。入门 8.介绍Spring Boot 9.系统要求 9.1.Servlet容器 10.安装Spring Boot 10.1.Java Developer的安装说明 10.1.1.Maven安装 10.1.2.Gradle安装 10.2.安装Spring Boot ...
Firefly是一个Web应用程序,旨在为Web开发人员提供功能强大,灵活的时间序列图。 Firefly提供了一个接口,用于从任意数量的服务器端数据存储中读取时间序列数据,并在Web浏览器中生成相应的实时图形。 多个度量可以...
4.7.4 连接池和DataSource实现 4.7.5 包含连接池的数据源配置 4.7.6 池连接对象对于语句的重新利用 4.7.7 关闭池连接语句 4.7.8 连接池使用实例 4.8 分布式事务处理 4.8.1 XADataSource接口和XAConnection接口...
1、你的应用需要访问的系统特性和设备通过Java平台是无法实现的。 2、你已经有了大量的测试和调试过的用另一种语言编写的代码,并且知道如何将其导出到所有的目标平台上 3、通过基准测试,你发现所编写的Java代码比...
聊天 LochChat 是一个针对大学生的小组讨论和协作工具,它允许多用户聊天以及同时编辑中央...cp grails-app/conf/DataSource.example.groovy /etc/grails/config/lochchat/DataSource.groovy cp grails-app/conf/Emai
Hwnd---------------表格句柄,可以结合Windows API对表格控件进行更高级的控制。 Text---------------指定当前的单元格的文本内容。 TextMatrix(i,j)-------此属性比较重要,它用来指定第I行和第j列所确定...