我们知道 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{
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();
}
}

因为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{
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();
}
}

通过以上优化,可以使你的封装类以最低的资源消耗来获取最大的性能.我们可以这样来进行测试:
把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"));
}
}
//当发生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进行一段时间(至少几天以上)跟踪,如果应用一直没有重启动,那就应该只产生一条
记录.这样你就有了一个顶级性能的封装类了

转自:

DataSource高级应用

【转】DataSource高级应用的更多相关文章

  1. JAVA高级编程数据源datasource

    原文链接 数据源 通过jdbc连接数据库,多建立几条连接放在数据源里面.可以设置数据源的最大连接数,同时活跃的连接数,最少空闲的连接数,能够同时接收处理的连接数等等. dbcp数据源 需要的jar包: ...

  2. JAVA高级编程(数据源datasource)

    数据源:通过jdbc连接数据库,多建立几条连接放在数据源里面.可以设置数据源的最大连接数,同时活跃的连接数,最少空闲的连接数,能够同时接收处理的连接数等等. dbcp数据源 需要的jar包: comm ...

  3. Mybatis高级查询之关联查询

    learn from:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps 关联查询 准备 关联结果查询(一对一) resul ...

  4. Webform(Linq高级查、分页、组合查询)

    一.linq高级查 1.模糊查(包含) 1 public List<User> Select(string name) 2 { 3 return con.User.Where(r => ...

  5. 如何轻松实现iOS9多任务管理器效果(iCarousel高级教程)

    前言 iOS9系统下 为了我司APP的兼容性问题 特意把手上的iOS Mac XCode都升级到了最新的beta版 然后发现iOS9的多任务管理器风格大变 变成了下面这种样子 我忽然想起来之前的文章提 ...

  6. 六 mybatis高级映射(一对一,一对多,多对多)

    1  订单商品数据模型 以订单商品数据为模型,来对mybaits高级关系映射进行学习.

  7. sp.net2.0中的新增控件BulletedList的一些高级用法

    asp.net2.0新增了一个BulletedList控件,通过它可以以列表形式显示数据,而不必再用Repeater,Datalist等实现相同的效果.今天做程序的时候正好用到了这个控件,就把它的一些 ...

  8. Java数据库连接——JDBC调用存储过程,事务管理和高级应用

    一.JDBC常用的API深入详解及存储过程的调用 相关链接:Jdbc调用存储过程 1.存储过程(Stored Procedure)的介绍 我们常用的操作数据库语言SQL语句在执行的时候需要先编译,然后 ...

  9. iOS开发——高级UI&带你玩转UITableView

    带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...

随机推荐

  1. 设计模式学习系列9 外观模式Facade

    1.概述 自己卖了一辆越野自行车,但毕竟不是自己定制的,买回来之后可能需要更改一下脚蹬,座皮,里程计数器或者刹车系统,假如将自行车看做一个整体系统,对我们而言使用的是自行车,然后我们对自己车构件的修改 ...

  2. the essence of the internet idea

    Computer Systems A Programmer's Perspective Second Edition Of course, we are glossing over many diff ...

  3. Transform.InverseTransformPoint 反向变换点

    JavaScript ⇒ public function InverseTransformPoint(position: Vector3): Vector3; C# ⇒public Vector3 I ...

  4. JDK核心包学习

    StringBuffer   线程安全.可变字符序列 StringBuilder   非线程安全.可变字符序列,比StringBuffer更快 Boolean 使用valueOf产生Boolean实例 ...

  5. 使用Nginx在自己的电脑上实现负载均衡

    我其实早就想弄这个负载均衡了,但是总觉得这玩意肯定不简单,今天星期六闲着没事终于下定决心来搞一搞他了,但是没想到这玩意这么简单,真的是出乎我的意料的简单(我现在陪的是最简单的那种).额是没有我想象中的 ...

  6. JVM内存状况查看方法和分析工具-jmap

    jmap -heap 27657 Attaching to process ID 27657, please wait... Debugger attached successfully. Serve ...

  7. java调用Http请求 -HttpURLConnection学习

    最常用的Http请求无非是get和post,get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,post与get的不同之处在于post的参数不是放在URL字串里面,而是放 ...

  8. linux与linux,linux与windows之间用SSH传输文件

    linux与linux,linux与windows之间用SSH传输文件linux与linux之间传送文件:scp file username@hostIP:文件地址    例: scp abc.txt ...

  9. Sql server中左连接语句

    数据库中学生表和课程表如下: 左连接sql语句: select a.studentName,a.studentAge,b.courseName from student a left join cou ...

  10. iOS开发中 在MRC中让某些类使用ARC编译 或者相反

    如果你的工程是MRC 想让某些类使用ARC进行编译的话 那么需要在Build Phases中Complile Sourse 把该类后面 写上如下命令:-fobjc-arc  反之 写上如下命令:-fn ...