首页 > 代码库 > 利用apache commons组件实现WEB应用跨多数据库

利用apache commons组件实现WEB应用跨多数据库


1、前言

在一些多数据库的环境中,有时候应用系统需要同时访问多个数据库,在流行的spring+hibernate等架构中,涉及要修改和调整的内容会比较多;如果直接用jdbc,那么代码里就要充斥很多的连接、关闭数据库、以及从数据库中进行循环取结果的代码,感觉总是不够优化。

         利用apachecommons 组件下的DBCP,dbUtils也能够编写相对比较优雅一点的代码。

本文主要提供更思路和方法,代码存在不够优化,架构存在不够清晰的情况,请辩证的看。

WEB应用涉及的东西有点多,写起来也挺繁琐的。如果有看不懂的地方,就多琢磨下吧,系统能正常运行的。

         基于JDK1.6,ORACLE10g,tomcat6 开发和测试。

        

2、需要的文件

         Oracle驱动:class12;commons-configuration-1.10.jar, commons-dbcp-1.4.jar,commons-dbutils-1.6.jar,commons-pool-1.6.jar在JRE5环境下,需要引入 struts2 core libraries库。

 

3、数据库表

两张

create table TB_STUDENT

(

 ID        INTEGER,

 NAME      VARCHAR2(256),

 SEX       VARCHAR2(256),

 AGE       VARCHAR2(256),

 GRADE     INTEGER,

 CLASSNAME VARCHAR2(256)

)

 

Create table tb_user(

username         VARCHAR2(256),

password      VARCHAR2(256)

)

 

4、整体架构

1个web文件,index.jsp 放在WebRoot目录下

1个数据库配置文件,db.properties复制两份,一份放在工程根目录下(做测试用),另外一份放在src目录下,供运行正式用;

1个struts.xml文件,放在src目录下

4个package,action,bean,dao,utils

 

5、目录结构截图:

技术分享

 

6utils

包括三个,一个读取配置文件,一个实现数据库连接,另外一个是一个tb_user的简单对象,供连接测试使用。

package cn.mrcast.util;

 

import org.apache.commons.configuration.CompositeConfiguration;

importorg.apache.commons.configuration.ConfigurationException;

importorg.apache.commons.configuration.PropertiesConfiguration;

 

/**

 * 通过commonsconfiguration进行简单的配置

 *

 *@author 范芳铭

 */

public class ConfigurationUsage {

         publicstatic void main(String[] args) {

                   StringjdbcUrl = propManager.getInstance().getProperty("jdbc.cms.url");

                   StringjdbcUsername = propManager.getInstance().getProperty(

                                     "jdbc.cms.username");

                   StringjdbcPassword = propManager.getInstance().getProperty(

                                     "jdbc.cms.password");

 

                   System.out.println("jdbcUrl:"+ jdbcUrl);

                   System.out.println("jdbcUsername:"+ jdbcUsername);

                   System.out.println("jdbcPassword:"+ jdbcPassword);

 

         }

 

         privateConfigurationUsage() {

         }

 

         privatestatic ConfigurationUsage propManager;

 

         publicsynchronized static ConfigurationUsage getInstance() {

                   if(propManager == null) {

                            propManager= new ConfigurationUsage();

                   }

                   returnpropManager;

         }

 

         publicstatic CompositeConfiguration config = new CompositeConfiguration();

         static{

                   try{

                            config.addConfiguration(newPropertiesConfiguration(

                                               "db.properties"));

                   }catch (ConfigurationException e) {

                            e.printStackTrace();

                   }

         }

 

         publicString getProperty(String key) {

                   returnconfig.getString(key);

         }

}

 

package cn.mrcast.util;

 

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Arrays;

import java.util.List;

import java.util.Map;

import java.util.Properties;

 

importorg.apache.commons.dbcp.BasicDataSource;

importorg.apache.commons.dbcp.BasicDataSourceFactory;

import org.apache.commons.dbutils.DbUtils;

importorg.apache.commons.dbutils.QueryRunner;

import org.apache.commons.dbutils.handlers.ArrayHandler;

importorg.apache.commons.dbutils.handlers.ArrayListHandler;

importorg.apache.commons.dbutils.handlers.BeanHandler;

importorg.apache.commons.dbutils.handlers.BeanListHandler;

import org.apache.commons.dbutils.handlers.ColumnListHandler;

importorg.apache.commons.dbutils.handlers.KeyedHandler;

importorg.apache.commons.dbutils.handlers.MapHandler;

importorg.apache.commons.dbutils.handlers.MapListHandler;

importorg.apache.commons.dbutils.handlers.ScalarHandler;

import org.apache.commons.lang.StringUtils;

 

/**

 * 通过commonsdbUtils进行数据库的简单访问和实用,版本: dbUtils1.6,Oracle驱动:class12;QueryRunner 代码实例

 *

 *@author 范芳铭

 */

public class DBUtils {

         staticConfigurationUsage propManager = null;

         privatestatic BasicDataSource dataSourceO2O = null;

         privatestatic BasicDataSource dataSourceBM = null;

 

 

         //连接O2O数据库

         publicstatic void initO2O() {

                   if(dataSourceO2O != null) {

                            try{

                                     dataSourceO2O.close();

                            }catch (Exception e) {

                                     e.printStackTrace();

                            }

                            dataSourceO2O= null;

                   }

                   try{ 

                            Propertiesp = new Properties();

                            p.setProperty("driverClassName",propManager.getInstance().getProperty("jdbc.o2o.driverClassName"));

                            p.setProperty("url",propManager.getInstance().getProperty("jdbc.o2o.url"));

                            p.setProperty("password",propManager.getInstance().getProperty("jdbc.o2o.username"));

                            p.setProperty("username",propManager.getInstance().getProperty("jdbc.o2o.password"));

                            p.setProperty("maxActive",propManager.getInstance().getProperty("jdbc.o2o.maxActive"));

                            p.setProperty("maxIdle",propManager.getInstance().getProperty("jdbc.o2o.maxIdle"));

                            p.setProperty("maxWait",propManager.getInstance().getProperty("jdbc.o2o.maxWait"));

 

                            dataSourceO2O= (BasicDataSource) BasicDataSourceFactory

                                               .createDataSource(p);

                   }catch (Exception e) {

                            e.printStackTrace();

                   }

         }

        

         //连接便民数据库

         publicstatic void initBM() {

                   if(dataSourceBM != null) {

                            try{

                                     dataSourceBM.close();

                            }catch (Exception e) {

                                     e.printStackTrace();

                            }

                            dataSourceBM= null;

                   }

                   try{ 

                            Propertiesp = new Properties();

                            p.setProperty("driverClassName",propManager.getInstance().getProperty("jdbc.bm.driverClassName"));

                            p.setProperty("url",propManager.getInstance().getProperty("jdbc.bm.url"));

                            p.setProperty("password",propManager.getInstance().getProperty("jdbc.bm.username"));

                            p.setProperty("username",propManager.getInstance().getProperty("jdbc.bm.password"));

                            p.setProperty("maxActive",propManager.getInstance().getProperty("jdbc.bm.maxActive"));

                            p.setProperty("maxIdle",propManager.getInstance().getProperty("jdbc.bm.maxIdle"));

                            p.setProperty("maxWait",propManager.getInstance().getProperty("jdbc.bm.maxWait"));

 

                            dataSourceBM= (BasicDataSource) BasicDataSourceFactory

                                               .createDataSource(p);

                   }catch (Exception e) {

                            e.printStackTrace();

                   }

         }

 

         publicstatic synchronized Connection getConnO2O() throws SQLException {

                   if(dataSourceO2O == null) {

                            initO2O();

                   }

                   Connectionconn = null;

                   if(dataSourceO2O != null) {

                            conn= dataSourceO2O.getConnection();

                   }

                   returnconn;

         }

        

         publicstatic synchronized Connection getConnBM() throws SQLException {

                   if(dataSourceBM == null) {

                            initBM();

                   }

                   Connectionconn = null;

                   if(dataSourceBM != null) {

                            conn= dataSourceBM.getConnection();

                   }

                   returnconn;

         }

         //内部使用和实例

         privateQueryRunner runner = null;

 

         publicDBUtils() {

                   initO2O();

                   runner= new QueryRunner(dataSourceO2O, true); //默认用O2O

         }

 

         publicstatic void main(String[] args) throws SQLException {

                   DBUtilsusage = new DBUtils();

                   usage.batch();

                   usage.fillStatement();

                   usage.query();

                   usage.closeDataSource();

         }

 

         privatevoid batch() {

                   Stringsql = "INSERT INTO tb_user (USERNAME, PASSWORD) values (?, ?)";

 

                   try{

                            System.out.println(StringUtils.center("TestQueryRunner batch", 50,

                                               ‘-‘));

                            int[]result = runner.batch(sql, new Object[][] {

                                               {"范芳铭1", "ffm1" }, { "范芳铭2","ffm2" },

                                               {"范芳铭3", "ffm3" }, { "范芳铭4","ffm" } });

                            System.out.printf("batch运行结果:", Arrays.toString(result));

                   }catch (SQLException ex) {

                            DbUtils.printStackTrace(ex);

                   }

         }

 

         privatevoid closeDataSource() throws SQLException {

                   ((BasicDataSource)dataSourceO2O).close();

         }

 

         privatevoid fillStatement() throws SQLException {

                   Stringsql = "INSERT INTO tb_user (USERNAME, PASSWORD) VALUES (?, ?)";

                   Connectionconn = null;

                   try{

                            System.out.println(StringUtils.center("TestQueryRunner fillStatement", 50,

                                                                 ‘-‘));

                            conn= dataSourceO2O.getConnection();

                            PreparedStatementpsmt = conn.prepareStatement(sql);

                            runner.fillStatementWithBean(psmt,

                                               newTb_user("范芳铭pstm", "ffm"), "username","password");

                            System.out.println("成功执行数据:"+ psmt.executeUpdate() + " 条");

                   }catch (SQLException ex) {

                            DbUtils.printStackTrace(ex);

                            ex.printStackTrace();

                   }finally {

                            DbUtils.commitAndCloseQuietly(conn);

                   }

         }

 

         //列举一些主要的查询形态

         privatevoid query() throws SQLException {

                   System.out.println(StringUtils

                                     .center("TestQueryRunner query", 50, ‘-‘));

                  

                   Stringsql = "SELECT * FROM tb_user WHERE rownum < ? ";

                  

                   //把ResultSet第一行包装成Object[]

                   System.out.println("  Test QueryRunner query, ArrayHandler");

                   Object[]r1 = runner.query(sql, new ArrayHandler(), "3");

                   System.out.println("  " + Arrays.deepToString(r1));

                  

                   //把ResultSet包装成List<Object[]>

                   System.out.println("  Test QueryRunner query,ArrayListHandler");

                   List<Object[]>r2 = runner.query(sql, new ArrayListHandler(), "3");

                   System.out.println("  " + Arrays.deepToString(r2.toArray()));

 

                   //把ResultSet第一行包装成一个List<JavaBean>;

                   System.out.println("Test QueryRunner query, BeanListHandler");

                   List<Tb_user>r4 = runner.query(sql, new BeanListHandler<Tb_user>(

                                     Tb_user.class),"3");

                   System.out.println("  " + Arrays.deepToString(r4.toArray()));

                  

                   //包装ResultSet,以Map<Object,Map<String,Object>>对象形式返回,第一个Object是指定的列值,第二个Map中String是列名且对大小写不敏感

                   System.out.println("TestQueryRunner query, KeyedHandler");

                   Map<Object,Map<String, Object>> r6 = runner.query(sql,

                                     newKeyedHandler(2), "3");

                   System.out.println("  " + r6.toString());

 

                   //把ResultSet包装成List<Map<String,Object>>>,Map的key对大小写不敏感

                   System.out.println("TestQueryRunner query, MapListHandler");

                   List<Map<String,Object>> r8 = runner.query(sql, new MapListHandler(),

                                     "3");

                   System.out.println("  " + r8.toString());

         }

}

 

package cn.mrcast.util;

/**

 * 通过commonsdbUtils进行数据库的简单访问和实用的javaBean

 *QueryRunner 代码实例

 *@author 范芳铭

 */

public class Tb_user {

         privateString username;

         privateString password;

        

         publicTb_user(){

         }

 

         publicTb_user(String username, String password) {

                   this.username= username;

                   this.password= password;

         }

 

         publicString getUsername() {

                   returnusername;

         }

 

         publicvoid setUsername(String username) {

                   this.username= username;

         }

 

         publicString getPassword() {

                  return password;

         }

 

         publicvoid setPassword(String password) {

                   this.password= password;

         }

        

         @Override

         publicString toString(){

                   return"name:" + username + ",pass:" + password;

         }

}

 

 

7Bean

就一个bean,student,在两个数据库中,对应的数据库的数据最好不一样,否则可能看不出效果。

package cn.mrcast.bean;

/**

 * 通过commonsdbUtils进行数据库的简单访问和实用的javaBean

 *QueryRunner 代码实例

 *@author 范芳铭

 */

public class Student {

         privateint id;

         privateString name;

   private String sex;

   private String age;

   private int grade;

   private String classname;

   public int getId() {

                   returnid;

         }

         publicvoid setId(int id) {

                   this.id= id;

         }

         publicString getName() {

                   returnname;

         }

         publicvoid setName(String name) {

                   this.name= name;

         }

         publicString getSex() {

                   returnsex;

         }

         publicvoid setSex(String sex) {

                   this.sex= sex;

         }

         publicString getAge() {

                   returnage;

         }

         publicvoid setAge(String age) {

                   this.age= age;

         }

         publicint getGrade() {

                   returngrade;

         }

         publicvoid setGrade(int grade) {

                   this.grade= grade;

         }

         publicString getClassname() {

                   returnclassname;

         }

         publicvoid setClassname(String classname) {

                   this.classname= classname;

         }

}

 

8Action

两个,一个访问A数据库,一个访问B数据库

package cn.mrcast.action;

 

import java.util.ArrayList;

import java.util.List;

 

importcom.opensymphony.xwork2.ActionSupport;

 

import cn.mrcast.bean.Student;

import cn.mrcast.dao.ShowAllDAO;

 

public class ShowAllAction extendsActionSupport {

         List<Student>list = new ArrayList<Student>();

         ShowAllDAOsd = new ShowAllDAO();

 

         publicList<Student> getList() {

                   returnlist;

         }

 

         publicString execute() {           

                   list= sd.useRunnerO2O_all();

                   return"success";

         }

}

 

package cn.mrcast.action;

 

import java.util.ArrayList;

import java.util.List;

 

importcom.opensymphony.xwork2.ActionSupport;

 

import cn.mrcast.bean.Student;

import cn.mrcast.dao.ShowAllDAO;

 

public class ShowBMAction extendsActionSupport {

         List<Student>list = new ArrayList<Student>();

         ShowAllDAOsd = new ShowAllDAO();

 

         publicList<Student> getList() {

                   returnlist;

         }

 

         publicString execute() {           

                   list= sd.useRunnerBM_all();

                   return"success";

         }

}

 

9Dao

一个类,包含了传统的JDBC使用的方式,以及新的方法作为对比

package cn.mrcast.dao;

 

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

 

import org.apache.commons.dbutils.DbUtils;

importorg.apache.commons.dbutils.QueryRunner;

importorg.apache.commons.dbutils.handlers.BeanListHandler;

 

import cn.mrcast.bean.Student;

import cn.mrcast.util.DBUtils;

import cn.mrcast.util.Tb_user;

/**

 * 通过commonsdbUtils进行数据库的简单访问和实用的javaBean,

 * 放了一个传统的数据库访问对象获取的样例作为对比

 *QueryRunner 代码实例

 *@author 范芳铭

 */

public class ShowAllDAO {

         privateQueryRunner runnerO2O = null;

         privateQueryRunner runnerBM = null;

        

        

         //如果不用 runner的方法,比较繁琐,不推荐使用

         publicList<Student> ShowAll() {

                   List<Student>list = new ArrayList<Student>();

                   Connectioncon = null;

                   try{

                            con= DBUtils.getConnO2O();

                            Stringsql = "select id,name,sex,age,grade,classname from tb_student";

                            PreparedStatementps = con.prepareStatement(sql);

                            ResultSetrs = ps.executeQuery();

                            while(rs.next()) {

                                     Studentst = new Student();

                                     st.setId(rs.getInt("id"));

                                     st.setName(rs.getString("name"));

                                     st.setSex(rs.getString("sex"));

                                     st.setAge(rs.getString("age"));

                                     st.setGrade(rs.getInt("grade"));

                                     st.setClassname(rs.getString("classname"));

                                     list.add(st);

                            }

                   }catch (SQLException e) {

                            System.out.println(e.getMessage());

                   }

                   returnlist;

         }

        

         publicList<Student> useRunnerO2O_all() {

                   List<Student>list = new ArrayList<Student>();

                   //oracle数据库连接初始化方法

                   runnerO2O= new QueryRunner(true);

                   Connectioncon = null;

                   try{

                            con= DBUtils.getConnO2O();

                            Stringsql = "select id,name,sex,age,grade,classname from tb_student";

                           

                            list= runnerO2O.query(con,sql, new BeanListHandler<Student>(Student.class));

                            System.out.println("  " +Arrays.deepToString(list.toArray()));

                   }catch (SQLException e) {

                            System.out.println(e.getMessage());

                   }finally{ 

           DbUtils.closeQuietly(con); 

       }

                   returnlist;

 

         }

        

         publicList<Student> useRunnerBM_all() {

                   List<Student>list = new ArrayList<Student>();

                   //oracle数据库连接初始化方法

                   runnerBM= new QueryRunner(true);

                   Connectioncon = null;

                   try{

                            con= DBUtils.getConnBM();

                            Stringsql = "select id,name,sex,age,grade,classname from tb_student";

                           

                            list= runnerBM.query(con,sql, new BeanListHandler<Student>(Student.class));

                            System.out.println("  " + Arrays.deepToString(list.toArray()));

                   }catch (SQLException e) {

                            System.out.println(e.getMessage());

                   }finally{ 

           DbUtils.closeQuietly(con); 

       }

                   returnlist;

 

         }

}

 

10、数据库配置文件

jdbc.o2o.driverClassName=oracle.jdbc.driver.OracleDriver

jdbc.o2o.url=jdbc:oracle:thin:@192.168.1.1:1521:ffm

jdbc.o2o.username=ffm

jdbc.o2o.password=ffm

jdbc.o2o.maxActive=20

jdbc.o2o.maxIdle=5

jdbc.o2o.maxWait=200

 

 

jdbc.bm.driverClassName=oracle.jdbc.driver.OracleDriver

jdbc.bm.url=jdbc:oracle:thin:@192.168.1.2:1521:TEST

jdbc.bm.username=test

jdbc.bm.password=test

jdbc.bm.maxActive=20

jdbc.bm.maxIdle=5

jdbc.bm.maxWait=200

 

11struts.xml配置文件

<?xml version="1.0"encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC "-//ApacheSoftware Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">

<struts>

<package name="first"extends="struts-default"><!-- 定义一个package -->

       

<!-- 对action返回结果的配置-->

         <actionname="showall" class="cn.mrcast.action.ShowAllAction">

                   <resultname="success">/index.jsp</result>

         </action>

        

                   <actionname="showBMall" class="cn.mrcast.action.ShowBMAction">

                   <resultname="success">/index.jsp</result>

         </action>

</package>

</struts>  

 

12web文件Index.jsp

<%@ page language="java"import="java.util.*" pageEncoding="GBK"%>

<%@taglib  uri="/struts-tags"prefix="s"%>

<%

String path = request.getContextPath();

String basePath =request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN">

<html>

<head>

   <base href=http://www.mamicode.com/"">

<title>My JSP ‘index.jsp‘ startingpage</title>

         <metahttp-equiv="pragma" content="no-cache">

         <metahttp-equiv="cache-control" content="no-cache">

         <metahttp-equiv="expires" content="0">   

         <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">

<meta http-equiv="description"content="This is my page">

   <style type="text/css">

<!--

.STYLE1 {

         font-size:18px;

         font-weight:bold;

}

-->

   </style>

</head>

 <body>

 <form action="showall.action" method="post"name="form1">

 <div align="center">

   <p class="STYLE1">&nbsp;</p>

   <p class="STYLE1">连接两个数据库,找学生成绩统计</p>

   <table width="392" border="1">

     <tr bgcolor="#FFCCFF">

       <td width="54"><div align="center">编号</div></td>

       <td width="58"><div align="center">姓名</div></td>

       <td width="52"><div align="center">性别</div></td>

       <td width="44"><div align="center">年龄</div></td>

       <td width="91"><div align="center">班级</div></td>

       <td width="53"><div align="center">成绩</div></td>

       <td width="53"><div align="center">级别</div></td>

     </tr>

   </table>

   <table width="392" border="1">

     <s:iterator id="student" value=http://www.mamicode.com/"list">

       <tr>

         <td width="54"><divalign="center"><s:property value=http://www.mamicode.com/"id"/>

         <td width="58"><divalign="center"><s:propertyvalue=http://www.mamicode.com/"name"/>

         <td width="52"><divalign="center"><s:propertyvalue=http://www.mamicode.com/"sex"/>

         <td width="44"><divalign="center"><s:property value=http://www.mamicode.com/"age"/>

         <td width="91"><divalign="center"><s:propertyvalue=http://www.mamicode.com/"classname"/>

         <td width="53"><divalign="center"><s:property value=http://www.mamicode.com/"grade"/>分

          <td width="53"><divalign="center"><s:if test = "#student.grade >= 60">及格</s:if>

          <s:else> 不及格</s:else>

          </div></td>

       </tr>

     </s:iterator>

     <tr align="center">

           <td colspan="2" bgcolor="#FFCCFF"><inputtype="submit" value=http://www.mamicode.com/"检索O2O数据库"/>>

           </td>

       </tr>

   </table>

 </div>

 </form>

 

   <form action="showBMall.action" method="post"name="form1">

 <div align="center">

   <table width="392" border="1">

     <tr align="center">

           <td colspan="2" bgcolor="#FFCCFF"><inputtype="submit" value=http://www.mamicode.com/"检索bm数据库"/>>

           </td>

       </tr>

   </table>

 </div>

 </form>

       调试信息的输出:

       <s:debug></s:debug>

 </body>

</html>

利用apache commons组件实现WEB应用跨多数据库