在一个应用里面,可能涉及到连接多个不同数据库进行操作,而每次连接写不同的实现会很麻烦。前面已经会了用JDBC连接数据库,那么利用反射和工厂模式,可以实现连接不同的数据库,这样处理起来将会很方便。同时建造数据库连接池,处理多个业务数据处理。
 
 

那么具体怎么实现呢,下面一起来看一下:
整体结构如下:

第一步,先处理连接不同数据库
1、首先,将数据库配置信息创建一个公用类:JdbcUrl.java
主数据库可以用默认的构造方法,如果是连接其他库,则通过传递参数的方式来处理。
数据库参数有如下几个:

 /**
* 数据库连接配置信息类
* @author Damon
*/
public class JdbcUrl
{ /** 定义数据库参数 */ // 数据库类型
private String DBType;
// 数据库服务器IP
private String IP;
// 数据库服务器端口
private String Port;
// 数据库名称
private String DBName;
// 用户名
private String UserName;
// 密码
private String PassWord; /**
* 默认构造方法,连接默认数据库
*/
public JdbcUrl()
{
// TODO Auto-generated constructor stub
DBType = SysCon.DATABASE_TYPE_MYSQL;
IP = "127.0.0.1";
DBName = "mysql";
Port = "3306";
UserName = "damon";
PassWord = "damon";
} /**
* 连接指定数据库
* @param urlType 传入连接类型标识
*/
public JdbcUrl(String urlType)
{
if ("mysql".equals(urlType))
{
DBType = SysCon.DATABASE_TYPE_MYSQL;
IP = "127.0.0.1";
DBName = "mysql";
Port = "3306";
UserName = "damon";
PassWord = "damon";
}
} /**
* 获取连接句柄
* @return String
*/
public String getJdbcUrl()
{
String sUrl = ""; if (DBType.trim().toUpperCase().equals("MYSQL"))
{
sUrl = "jdbc:mysql://" + IP + ":" + Port + "/" + DBName;
}
else if (DBType.trim().toUpperCase().equals("DB2"))
{
sUrl = "jdbc:db2://" + IP + ":" + Port + "/" + DBName;
} else if (DBType.trim().toUpperCase().equals("ORACLE"))
{
sUrl = "jdbc:oracle:thin:@" + IP + ":" + Port + ":" + DBName;
} else if (DBType.trim().toUpperCase().equals("SQLSERVER"))
{
sUrl = "jdbc:microsoft:sqlserver://" + IP + ":" + Port + ";databaseName=" + DBName + ";selectMethod=cursor";
}
else if (DBType.trim().toUpperCase().equals("WEBLOGICPOOL"))
{
sUrl = "jdbc:weblogic:pool:" + DBName;
}
else
{
System.out.println("暂无对应数据库驱动");
}
return sUrl;
} // getters and setters public String getDBType()
{
return DBType;
} public void setDBType(String dBType)
{
DBType = dBType;
} public String getIP()
{
return IP;
} public void setIP(String iP)
{
IP = iP;
} public String getPort()
{
return Port;
} public void setPort(String port)
{
Port = port;
} public String getDBName()
{
return DBName;
} public void setDBName(String dBName)
{
DBName = dBName;
} public String getUserName()
{
return UserName;
} public void setUserName(String userName)
{
UserName = userName;
} public String getPassWord()
{
return PassWord;
} public void setPassWord(String passWord)
{
PassWord = passWord;
} }

2、重写一个Connection类,实现Connection接口的方法,同时连接数据库。

参数有已实现的JdbrUrl类,主要新增方法为:createConnection()
根据DBType来对不同数据库进行处理:加载对应的数据库,然后获取数据库连接。
 **
* 数据库连接类,连接数据库
* @author Damon
*/
public class DBConn implements Connection
{ // 获取JdbcUrl信息
private JdbcUrl JUrl; // 数据库连接
private Connection con = null; // 连接是否已使用
private boolean bNotInUse; private CharArrayWriter m_buf = new CharArrayWriter(); private PrintWriter m_pw = new PrintWriter(m_buf, true); // 默认连接
public DBConn()
{
// TODO Auto-generated constructor stub
this.JUrl = new JdbcUrl();
} // 指定数据库连接
public DBConn(String urlType)
{
this.JUrl = new JdbcUrl(urlType);
} // 创建连接
public boolean createConnection()
{ // 根据数据库类型加载驱动及连接
try
{
// 连接MySQL数据库
if (SysCon.DATABASE_TYPE_MYSQL.equals(JUrl.getDBType()))
{
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver"); // 尝试连接数据库
con = DriverManager.getConnection(JUrl.getJdbcUrl(), JUrl.getUserName(), JUrl.getPassWord());
}
// 其他数据库类型判断及处理
// SQLSERVER
else if (SysCon.DATABASE_TYPE_SQLSERVER.equals(JUrl.getDBType()))
{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
con = DriverManager.getConnection(JUrl.getJdbcUrl(), JUrl.getUserName(), JUrl.getPassWord());
}
// DB2
else if (SysCon.DATABASE_TYPE_DB2.equals(JUrl.getDBType()))
{
Class.forName("com.ibm.db2.jcc.DB2Driver");
con = DriverManager.getConnection(JUrl.getJdbcUrl(), JUrl.getUserName(), JUrl.getPassWord());
}
// ORACLE
else if (SysCon.DATABASE_TYPE_ORACLE.equals(JUrl.getDBType()))
{
Class.forName("oracle.jdbc.driver.OracleDriver");
// 一个是缓存取到的记录数,一个是设置默认的批量提交数
Properties props = new Properties();
props.setProperty("user", JUrl.getUserName());
props.setProperty("password", JUrl.getPassWord());
props.setProperty("defaultRowPrefetch", "50");
props.setProperty("defaultExecuteBatch", "50");
con = DriverManager.getConnection(JUrl.getJdbcUrl(), props);
}
else
{
System.out.println("未匹配到数据库类型!");
return false;
} }
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
System.out.println("加载驱动失败!");
e.printStackTrace();
return false;
}
catch (SQLException e)
{
// TODO Auto-generated catch block
System.out.println("创建连接失败..." + e.getMessage());
e.printStackTrace();
return false;
}
return true;
} protected void setInUse()
{
/**
* Record stack information when each connection is get We reassian
* System.err, so Thread.currentThread().dumpStack() can dump stack info
* into our class FilterPrintStream.
*/
new Throwable().printStackTrace(m_pw); bNotInUse = false; /**
* record lastest access time
*/
} /* 下面都是 实现Connection的方法,返回conn的实现 */
public <T> T unwrap(Class<T> iface) throws SQLException
{
// TODO Auto-generated method stub
return con.unwrap(null);
} public boolean isWrapperFor(Class<?> iface) throws SQLException
{
// TODO Auto-generated method stub
return false;
} public Statement createStatement() throws SQLException
{
// TODO Auto-generated method stub
return con.createStatement();
} public PreparedStatement prepareStatement(String sql) throws SQLException
{
// TODO Auto-generated method stub
return con.prepareStatement(sql);
} public CallableStatement prepareCall(String sql) throws SQLException
{
// TODO Auto-generated method stub
return con.prepareCall(sql);
} public String nativeSQL(String sql) throws SQLException
{
// TODO Auto-generated method stub
return con.nativeSQL(sql);
} public void setAutoCommit(boolean autoCommit) throws SQLException
{
// TODO Auto-generated method stub
con.setAutoCommit(autoCommit);
} public boolean getAutoCommit() throws SQLException
{
// TODO Auto-generated method stub
return con.getAutoCommit();
} public void commit() throws SQLException
{
// TODO Auto-generated method stub
con.commit();
} public void rollback() throws SQLException
{
// TODO Auto-generated method stub
con.rollback();
} public void close() throws SQLException
{
// TODO Auto-generated method stub
con.close();
} public boolean isClosed() throws SQLException
{
// TODO Auto-generated method stub return con.isClosed();
} public DatabaseMetaData getMetaData() throws SQLException
{
// TODO Auto-generated method stub
return con.getMetaData();
} public void setReadOnly(boolean readOnly) throws SQLException
{
// TODO Auto-generated method stub
con.setReadOnly(readOnly);
} public boolean isReadOnly() throws SQLException
{
// TODO Auto-generated method stub
return con.isReadOnly();
} public void setCatalog(String catalog) throws SQLException
{
// TODO Auto-generated method stub
con.setCatalog(catalog);
} public String getCatalog() throws SQLException
{
// TODO Auto-generated method stub
return con.getCatalog();
} public void setTransactionIsolation(int level) throws SQLException
{
// TODO Auto-generated method stub
con.setTransactionIsolation(level);
} public int getTransactionIsolation() throws SQLException
{
// TODO Auto-generated method stub
return con.getTransactionIsolation();
} public SQLWarning getWarnings() throws SQLException
{
// TODO Auto-generated method stub
return con.getWarnings();
} public void clearWarnings() throws SQLException
{
// TODO Auto-generated method stub
con.clearWarnings();
} public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
{
// TODO Auto-generated method stub
return con.createStatement(resultSetType, resultSetConcurrency);
} public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException
{
// TODO Auto-generated method stub
return con.prepareStatement(sql, resultSetType, resultSetConcurrency);
} public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
// TODO Auto-generated method stub
return con.prepareCall(sql, resultSetType, resultSetConcurrency);
} public Map<String, Class<?>> getTypeMap() throws SQLException
{
// TODO Auto-generated method stub
return con.getTypeMap();
} public void setTypeMap(Map<String, Class<?>> map) throws SQLException
{
// TODO Auto-generated method stub
con.setTypeMap(map);
} public void setHoldability(int holdability) throws SQLException
{
// TODO Auto-generated method stub
con.setHoldability(holdability);
} public int getHoldability() throws SQLException
{
// TODO Auto-generated method stub
return con.getHoldability();
} public Savepoint setSavepoint() throws SQLException
{
// TODO Auto-generated method stub
return con.setSavepoint();
} public Savepoint setSavepoint(String name) throws SQLException
{
// TODO Auto-generated method stub
return con.setSavepoint(name);
} public void rollback(Savepoint savepoint) throws SQLException
{
// TODO Auto-generated method stub
con.rollback(savepoint);
} public void releaseSavepoint(Savepoint savepoint) throws SQLException
{
// TODO Auto-generated method stub
con.releaseSavepoint(savepoint);
} public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException
{
// TODO Auto-generated method stub
return con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
} public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException
{
// TODO Auto-generated method stub
return con.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
} public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException
{
// TODO Auto-generated method stub
return null;
} public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
{
// TODO Auto-generated method stub
return con.prepareStatement(sql, autoGeneratedKeys);
} public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
{
// TODO Auto-generated method stub
return con.prepareStatement(sql, columnIndexes);
} public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
{
// TODO Auto-generated method stub
return con.prepareStatement(sql, columnNames);
} public Clob createClob() throws SQLException
{
// TODO Auto-generated method stub
return con.createClob();
} public Blob createBlob() throws SQLException
{
// TODO Auto-generated method stub
return con.createBlob();
} public NClob createNClob() throws SQLException
{
// TODO Auto-generated method stub
return con.createNClob();
} public SQLXML createSQLXML() throws SQLException
{
// TODO Auto-generated method stub
return con.createSQLXML();
} public boolean isValid(int timeout) throws SQLException
{
// TODO Auto-generated method stub
return con.isValid(timeout);
} public void setClientInfo(String name, String value) throws SQLClientInfoException
{
// TODO Auto-generated method stub
con.setClientInfo(name, value);
} public void setClientInfo(Properties properties) throws SQLClientInfoException
{
// TODO Auto-generated method stub
con.setClientInfo(properties);
} public String getClientInfo(String name) throws SQLException
{
// TODO Auto-generated method stub
return con.getClientInfo(name);
} public Properties getClientInfo() throws SQLException
{
// TODO Auto-generated method stub
return con.getClientInfo();
} public Array createArrayOf(String typeName, Object[] elements) throws SQLException
{
// TODO Auto-generated method stub
return con.createArrayOf(typeName, elements);
} public Struct createStruct(String typeName, Object[] attributes) throws SQLException
{
// TODO Auto-generated method stub
return con.createStruct(typeName, attributes);
} }

3、公共的数据库连接池

数据库配置和数据库连接已经搞定,那么可以建一个数据库连接池来进行数据库的连接及处理。
主要有2个方法,连接默认数据库和连接指定的数据库。
 /**
* 获取默认数据库连接
* @param uri
* @return
*/
public static DBConn getConnection()
{
DBConn dbConn = new DBConn();
if (!dbConn.createConnection())
{
// 如果创建连接失败
DBSemaphore.unLock();
return null;
} // 连接成功,设置该连接属性
try
{
// 特殊处理连接的AutoCommit是否已经被设置
dbConn.setAutoCommit(true);
dbConn.setInUse();
DBSemaphore.unLock();
return dbConn;
}
catch (Exception ex)
{
ex.printStackTrace();
DBSemaphore.unLock();
return null;
} } /**
* 通过URI地址获取指定数据库连接
* @param uri
* @return
*/
public static DBConn getConnection(String uri)
{
DBConn dbConn = new DBConn(uri);
if (!dbConn.createConnection())
{
// 如果创建连接失败
// DBSemaphore.UnLock();
return null;
}
try
{
// 特殊处理连接的AutoCommit是否已经被设置
dbConn.setAutoCommit(true);
// dbConn.setInUse();
// DBSemaphore.UnLock();
return dbConn;
}
catch (Exception ex)
{
ex.printStackTrace();
// DBSemaphore.UnLock();
return null;
} }
可以写一个测试方式,这也数据库连接就完成了,通过传入不同的参数就可以获取到不同数据库的连接了。

     public static void main(String[] args)
{
// 测试连接池 // 1、连接mysql 数据库
Connection conn = DBConnPool.getConnection(); if (conn == null)
{
System.out.println("获取连接失败!");
}
else
{
System.out.println("获取连接成功");
} }
第二步,构建数据库连接池
前面已经实现连接不同数据库,那么怎么处理为连接池呢?
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。下面我们就来实现数据库连接池的功能:

数据库连接池的实现思想主要有如下几个方面:
1、可定义最大和最小的连接数:如果请求小于最小连接数,则直接分配连接,达到最大连接数则新请求等待;
2、用户在连接数据库时,不用新建连接,而是直接从连接池中获取连接,使用完毕后也不用关闭,而是释放给连接池,供下一个用户使用;
下面来进行实现:
其实就是实现了一个数据连接数的判断,最大连接数进行限制,实际的数据库连接池需结合对应的数据库连接池组件(比如 WebSphere等中间件),在判断是否有连接在使用的时候,会涉及到并发,这里需要用到volatile关键字。
 
其中,增加了DBsemaphor类,用以处理连接的使用和释放。
在原有DBConn基础上,加上是否已使用方法,在获取连接成功时调用,具体代码如下:

 // 连接成功,设置该连接属性
try
{
// 特殊处理连接的AutoCommit是否已经被设置
dbConn.setAutoCommit(true);
dbConn.setInUse();
DBSemaphore.unLock();
return dbConn;
}
catch (Exception ex)
{
ex.printStackTrace();
DBSemaphore.unLock();
return null;
}

新增DBSemaphore类属性及方法如下:

 /**
* 数据库同步对象
* @author Damon
*/
public class DBSemaphore
{
private static volatile boolean m_bInUse = false; public DBSemaphore()
{} /**
* 设置"使用标志"。 传入true表示请求“使用标志”,传入false表示释放“使用标志”。
* @param bNewValue boolean
* @return boolean
*/
protected static synchronized boolean setInUseFlag(boolean bNewValue)
{
if (bNewValue == true)
{
// 请求“使用标志”
if (m_bInUse == true)
{
// “使用标志”已经被占用
return false;
}
else
{
m_bInUse = true;
return true;
}
}
else
{
// 释放“使用标志”
m_bInUse = false;
return true;
}
} protected static void lock() throws Exception
{
lock(0);
} protected static void lock(int nSeconds) throws Exception
{
if (nSeconds <= 0)
{
while (!setInUseFlag(true))
{
Thread.sleep(100);
}
}
else
{
while (!setInUseFlag(true) && nSeconds-- > 0)
{
Thread.sleep(100);
} if (nSeconds == 0)
{
throw new Exception("Lock time out");
}
}
} protected static void unLock()
{
setInUseFlag(false);
}
}

到这里,整个配置处理结束了,更多的就需要在实际项目中发挥了~

 

Java创建连接池连接不同数据库的更多相关文章

  1. JNDI连接池连接Oracle数据库

    今天做了一个评论的小功能,要求用JNDI连接池连接Oracle数据库,以前只是测试了是否连接的上,现在没想到一个JNDI连接池连接Oracle数据库,纠结了好久,原来都是Oracle数据库的问题,这是 ...

  2. python使用dbutils的PooledDB连接池,操作数据库

    1.使用dbutils的PooledDB连接池,操作数据库. 这样就不需要每次执行sql后都关闭数据库连接,频繁的创建连接,消耗时间 2.如果是使用一个连接一直不关闭,多线程下,插入超长字符串到数据库 ...

  3. spring boot配置druid连接池连接mysql

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  4. node 连接MySQL及其分装, 连接池连接

    const mysql = require('mysql') const config = require('./../../config/config.default') var connectio ...

  5. python通过连接池连接redis,操作redis队列

    在每次使用redis都进行连接的话会拉低redis的效率,都知道redis是基于内存的数据库,效率贼高,所以每次进行连接比真正使用消耗的资源和时间还多.所以为了节省资源,减少多次连接损耗,连接池的作用 ...

  6. Java使用数据库连接池连接Oracle数据库

    第一步:导入tomcat\lib 下的一个tomcat-dbcp.jar包第二步:在web\META-INF下新建一个context.xml文件,文件内容如下: <?xml version=&q ...

  7. Spring框架中 配置c3p0连接池 完成对数据库的访问

    开发准备: 1.导入jar包: ioc基本jar jdbcTemplate基本jar c3p0基本jar 别忘了mysql数据库驱动jar 原始程序代码:不使用配置文件方式(IOC)生成访问数据库对象 ...

  8. 关于c3p0连接池连接mysql数据库需要注意的几点

    什么是数据库连接池: 用池来管理Connection,这可以重复使用Connection.有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象. 当使用完Co ...

  9. python - DBUtils 连接池减少oracle数据库的连接数

    问题: 接到需求,告知项目的oracle连接次数过多,对系统造成太过大的负担,要求减少oracle数据库的连接次数 分析: 仔细分析代码以后,发现产生问题的原因,在于之前要求提升oracle监控的监控 ...

随机推荐

  1. Ch.3 Aray and String

    3-1 scrore  Here is a string with o and x. The length is between 1 to 80. Calcuate the score. The sc ...

  2. Windows下用Composer引入官方GitHub扩展包

    Windows下用Composer引入官方GitHub扩展包 1. 当你打开威武RC4版本的链接的时候,往下拉你可以看到这个,然后你要做的就是想到,百度Composer,看看是个什么鬼,别想太多,跟着 ...

  3. socket获取百度页面

    import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import jav ...

  4. 16.3Sum Closet

    思路: 暴力,复杂度为 \(O(n^3)\),超时 class Solution { public: int threeSumClosest(vector<int>& nums, ...

  5. Spring学习(7)--- @Required注解

    @Required注解是用于bean属性的setter方法 这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在bean定义胡通过自动装配一个明确的属性值 package com.mypa ...

  6. Vue2 全家桶仿 微信App 项目,支持多人在线聊天和机器人聊天

    前言 这个项目是利用工作之余写的一个模仿微信app的单页面应用,整个项目包含27个页面,涉及实时群聊,机器人聊天,同学录,朋友圈等等,后续页面还是开发中.写这个项目主要目的是练习和熟悉vue和vuex ...

  7. 开始学习机器学习,从Ng的视频开始

    时隔开5个月,忙完了考研和毕设后终于有时间搞自己想搞得,研究生导师方向是图像处理与机器学习结合,重新开工 何为机器学习? 对于机器学习(Machine Learning)的定义大体上有两种,第一种是美 ...

  8. python 解析docx文档的方法,以及利用Python从docx文档提取插入的文本对象和图片

    首先安装docx模块,通过pip install docx或者在docx官方链接上下载安装都可以 下面来看下如何解析docx文档:文档格式如下 有3个部分组成 1 正文:text文档 2 一个表格. ...

  9. 【转载】Sublime Text 3065 Keygen and Patcher

    原始日期:2014-10-01 18:25      差不多时隔一年了,Sublime Text 终于更新啦!相信很多友友都已经升级到3065版本了,所以我也特地抽空为大家做了个新版补丁.该补丁仅作为 ...

  10. 关于Iscroll.js 的滑动和Angular.js路由冲突问题

    Iscroll主要应用于app移动端开发. 主要代码: window.onload=function(){ var myIscroll=new IScroll(".headerNav&quo ...