zoukankan      html  css  js  c++  java
  • JDBC数据源(DataSource)数据源技术是Java操作数据库的一个很关键技术,流行的持久化框架都离不开数据源的应用。

    JDBC数据源(DataSource)的简单实现
     
    数据源技术是Java操作数据库的一个很关键技术,流行的持久化框架都离不开数据源的应用。
    2.数据源提供了一种简单获取数据库连接的方式,并能在内部通过一个池的机制来复用数据库连接,这样就大大减少创建数据库连接的次数,提高了系统性能。
    3.对于数据源的应用,一般都选择实用开源的数据源或数据库连接池来使用,比如,常见的有DBCP、C3P0、Proxool等等。
     
    下面自己手动实现个精简的数据源,代码如下:
     
    package com.lavasoft.simpledatesource; 

    import org.apache.commons.logging.Log; 
    import org.apache.commons.logging.LogFactory; 

    import javax.sql.DataSource; 
    import java.util.Collections; 
    import java.util.LinkedList; 
    import java.sql.Connection; 
    import java.sql.SQLException; 
    import java.sql.DriverManager; 
    import java.io.PrintWriter; 

    /** 
    * 一个简单的DataSource实现 

    * @author leizhimin 2010-1-14 0:03:17 
    */
     
    public class SimpleDateSource implements DataSource { 
            private static Log log = LogFactory.getLog(SimpleDateSource.class); 
            private static final String dirverClassName = "com.mysql.jdbc.Driver"
            private static final String url = "jdbc:mysql://127.0.0.1:3306/testdb"; 
            private static final String user = "root"
            private static final String pswd = "leizhimin"
            //连接池 
            private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedList(new LinkedList<Connection>()); 
            private static SimpleDateSource instance = new SimpleDateSource(); 

            static { 
                    try { 
                            Class.forName(dirverClassName); 
                    } catch (ClassNotFoundException e) { 
                            log.error("找不到驱动类!", e); 
                    } 
            } 

            private SimpleDateSource() { 
            } 

            /** 
             * 获取数据源单例 
             * 
             * @return 数据源单例 
             */
     
            public SimpleDateSource instance() { 
                    if (instance == null) instance = new SimpleDateSource(); 
                    return instance; 
            } 

            /** 
             * 获取一个数据库连接 
             * 
             * @return 一个数据库连接 
             * @throws SQLException 
             */
     
            public Connection getConnection() throws SQLException { 
                    synchronized (pool) { 
                            if (pool.size() > 0) return pool.removeFirst(); 
                            else return makeConnection(); 
                    } 
            } 

            /** 
             * 连接归池 
             * 
             * @param conn 
             */
     
            public static void freeConnection(Connection conn) { 
                    pool.addLast(conn); 
            } 

            private Connection makeConnection() throws SQLException { 
                    return DriverManager.getConnection(url, user, pswd); 
            } 

            public Connection getConnection(String username, String password) throws SQLException { 
                    return DriverManager.getConnection(url, username, password); 
            } 

            public PrintWriter getLogWriter() throws SQLException { 
                    return null
            } 

            public void setLogWriter(PrintWriter out) throws SQLException { 

            } 

            public void setLoginTimeout(int seconds) throws SQLException { 

            } 

            public int getLoginTimeout() throws SQLException { 
                    return 0; 
            } 

            public <T> T unwrap(Class<T> iface) throws SQLException { 
                    return null
            } 

            public boolean isWrapperFor(Class<?> iface) throws SQLException { 
                    return false
            } 
    }
     
    这个数据源的实现虽然很简陋,总代码量不到百行,却基本上实现了数据源的所有功能,达到了提高Connection复用的目的。
     
    如果你想做的更复杂些,做个配置文件,
    配置数据库连接信息
    写个后台线程监控连接池的Connection超时、被强制关闭、池的尺寸、当前大小等等。
    再完善下数据源的log相关方法的实现。
     

    DataSource接口(javax.sql.DataSource)替代DriverManager获取Connection的方法,有以下好处:

    • 可以在部署时灵活更换Connection实现;
    • 可以更好的屏蔽数据库的相关性。

    以下以Oracle为例说明。

    使用厂商DataSource

    数据库厂商在提高JDBC2.0和以上版本的JDBC驱动中应该包含厂商的DataSource实现。

    OracleDataSource ods = new OracleDataSource();
    ods.setUser(“my_user”);
    ods.setPassword(“my_password”);
    ods.setURL(“jdbc:oracle:thin:@<database>”);
    Connection conn = ods.getConnection();

    第三方DataSource

    第三方厂商也可提供DataSource实现,比如免费开源的有DBCP,C3P0和proxool等,中间件厂商比如ibm的websphere,bea的weblogic等也都有实现。

    以下是DBCP的示例:

    BasicDataSource basicDataSource = new BasicDataSource(); basicDataSource.setDriverClassName(“oracle.jdbc.OracleDriver”); basicDataSource.setUrl(“jdbc:oracle:thin:@<database>”); basicDataSource.setUsername(“user”);basicDataSource.setPassword(“password”); Connection connection=basicDataSource.getConnection();

    结合JNDI的DataSource

    以tomcat为例,将数据库驱动库复制到{tomcat}/commmon/lib目录下。

    配置{tomcat}/conf/context.xml文件,加入:

    <Resource name=”jdbc/demo” auth=”Container” type=”javax.sql.DataSource”
            driverClassName=”org.apache.derby.jdbc.ClientDriver”
            url=”jdbc:derby://localhost:1527/demo”
            username=”test”
            password=”test”
            maxActive=”2″
            maxIdle=”1″
            removeAbandoned=”true”
            maxWait=”300″ />

    在程序中访问DataSource:

    Context initContext = new InitialContext();

    // 注意: 以下写法只适用于tomcat(Java:/comp/env).
    Context envContext = (Context) initContext.lookup(“java:/comp/env”);
    dataSource = (DataSource) envContext.lookup(“jdbc/demo”);

    配置内容也可以加到webapp/META-INF/context.xml文件中,这样更便于打包部署。

    <%@page import="java.sql.*, javax.sql.*, javax.naming.*"%>
    <html>
    <head>
    <title>Using a DataSource</title>
    </head>
    <body>
    <h1>Using a DataSource</h1>
    <%
        DataSource ds = null;
        Connection conn = null;
        ResultSet result = null;
        Statement stmt = null;
        ResultSetMetaData rsmd = null;
        try{
          Context context = new InitialContext();
          Context envCtx = (Context) context.lookup("java:comp/env");
          ds =  (DataSource)envCtx.lookup("jdbc/address");
          if (ds != null) {
            conn = ds.getConnection();
            stmt = conn.createStatement();
            result = stmt.executeQuery("SELECT * FROM AddressList");
           }
         }
         catch (SQLException e) {
            System.out.println("Error occurred " + e);
          }
          int columns=0;
          try {
            rsmd = result.getMetaData();
            columns = rsmd.getColumnCount();
          }
          catch (SQLException e) {
             System.out.println("Error occurred " + e);
          }
     %>
     <table width="90%" border="1">
       <tr>
       <% // write out the header cells containing the column labels
          try {
             for (int i=1; i<=columns; i++) {
                  out.write("<th>" + rsmd.getColumnLabel(i) + "</th>");
             }
       %>
       </tr>
       <% // now write out one row for each entry in the database table
             while (result.next()) {
                out.write("<tr>");
                for (int i=1; i<=columns; i++) {
                  out.write("<td>" + result.getString(i) + "</td>");
                }
                out.write("</tr>");
             }
     
             // close the connection, resultset, and the statement
             result.close();
             stmt.close();
             conn.close();
          } // end of the try block
          catch (SQLException e) {
             System.out.println("Error " + e);
          }
          // ensure everything is closed
        finally {
         try {
           if (stmt != null)
            stmt.close();
           }  catch (SQLException e) {}
           try {
            if (conn != null)
             conn.close();
            } catch (SQLException e) {}
        }
     
        %>
    </table>
    </body>
    </html>

  • 相关阅读:
    安装 Panda3D 并使用原有的Python
    Jupyter Notebook PDF输出的中文支持
    lua的文件管理
    elasticsearch-hadoop.jar, 适用于spark3,hadoop3
    shell中递归遍历指定文件夹下的文件
    JDBC的ResultSet游标转spark的DataFrame,数据类型的映射以TeraData数据库为例
    Pandas一些小技巧
    用c++后缀自动机实现最大公共字符串算法,并封装成Python库
    后缀自动机的python实现
    PYTHON调用C接口(基于Ctypes)实现stein算法最大公约数的计算
  • 原文地址:https://www.cnblogs.com/panxuejun/p/7264103.html
Copyright © 2011-2022 走看看