import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class DCDashBoardConnectionFactory { private static Connection connection; private static String connectionURL = "jdbc:oracle:thin:@192.168.2.5:1521:DASHBOARD"; private static String username = "system"; private static String password = "system"; private static String CONFIG_LOCATION_FILE = "config.xml"; private static File configFile; private static Document document; private static Statement statement;

private static Logger log =Logger.getLogger("com.dashboard.dao.DCDashBoardConnectionFactory");

public DCDashBoardConnectionFactory() {
} private static void getConfig() {
log.info("Reading config file...");
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
if (configFile == null)
configFile = new File(CONFIG_LOCATION_FILE);
if (document == null) {
try {
builder = df.newDocumentBuilder();
document = builder.parse(configFile);
document.normalize();
} catch (Exception e) {
e.printStackTrace();
}
} NodeList urlList = (NodeList) document.getElementsByTagName("url");
Element urlelement = (Element) urlList.item(0);
Node nodeURL = urlelement.getChildNodes().item(0);
connectionURL = nodeURL.getNodeValue();
log.info("Read coonectionURL ok!");
NodeList usernameList = (NodeList) document
.getElementsByTagName("username");
Element usernameElement = (Element) usernameList.item(0);
Node usernameNode = usernameElement.getChildNodes().item(0);
username = usernameNode.getNodeValue();
log.info("Read username ok;");
NodeList passwordList = (NodeList) document
.getElementsByTagName("password");
Element passwordElement = (Element) passwordList.item(0);
Node passwordNode = passwordElement.getChildNodes().item(0);
password = passwordNode.getNodeValue();
log.info("Read password ok;"); } private static void initConnection() {
getConfig();
try {
Class.forName("oracle.jdbc.OracleDriver");
connection = DriverManager.getConnection(connectionURL, username,
password);
log.info("Connection ok!");
} catch (ClassNotFoundException e) {
log.error(e.toString());
} catch (SQLException e) {
log.error(e.toString());
}
} private static Connection getConnection() {
if (connection == null) {
initConnection();
}
return connection;
} public static Statement getStatement() {
if (statement == null) {
try {
statement = getConnection().createStatement();
} catch (SQLException e) {
log.error(e.toString());
}
}
return statement;
}}

解决方案 »

  1.   

    我的用户上已经没有分啦,等分有啦,再追加分数,大家帮我看看啊,有什么不妥的地方,给改改啊!
    这是我为公司设计的第一个jdbc公用链接类啊!我不想它在使用的时候出故障啊,大家帮我看看啊!而且本人有一个小问题,就是怎么判断statement已经close?if colse 的话,就重新getStatement一次,否则就用全局静态的statement。
      

  2.   

    一般来说,连接池中的 Connection 在用完之后并不是真正的关掉,但是为了防止用户使用
    close() 方法关掉连接的话,一般需要采用动态代理技术把 close() 方法给屏蔽掉,当用
    户在使用 close() 方法时,只是将其归还到池中,而不是真正的关掉,这样才可以保证连
    接的重用。我原来写的一个连接工厂(实际上不是连接池,只是在整个应用中只存在一个连接,用于单机测试)参考一下:import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;import com.util.DatabaseUtil;public class ConnectionFactory { private static Connection con = null; private ConnectionFactory() {
    } /**
     * 采用单例模式的连接工厂
     * 
     * @return
     * @throws SQLException
     */
    public synchronized static Connection getConnection() throws SQLException {
    if (con == null || con.isClosed()) {
    try {
    // DatabaseUtil.getXXXX 是从配置文件中读取连接数据
    Class.forName(DatabaseUtil.getDriver());
    String url = DatabaseUtil.getUrl();
    String username = DatabaseUtil.getUsername();
    String password = DatabaseUtil.getPassword();
    con = DriverManager.getConnection(url, username, password);
    ConnectionHandler conHandler = new ConnectionHandler();
    con = conHandler.bind(con);
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    }
    return con;
    }
    }/**
     * 利用动态代理,在调用 close() 时并不真正的关闭 Connection,
     * 便于重用,在单机用户中始终只存在一个 Connection,提高连接速度
     * @author Administrator
     */
    class ConnectionHandler implements InvocationHandler {
    private Connection con = null;
    public Connection bind(Connection connection) {
    con = connection;
    Connection conProxy = (Connection)Proxy.newProxyInstance(
    connection.getClass().getClassLoader(),
    connection.getClass().getInterfaces(),
    this
    );
    return conProx
    }

    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
    Object obj = null;
    // 当调用 close() 时什么都不做,若是连接池的话
    // 可以在 close() 中把连接归还到池中
    if(!method.getName().equals("close")) {
    obj = method.invoke(con, args);
    }
    return obj;
    }
    }当然了,如果要制作真正的连接池除了要使用数据结构来存放连接外,还需要考虑很多的问题,比如:
    连接超时的回收、并发状态下的连接管理等等,要实现一个真正意义上的连接池是极其复杂的。
      

  3.   

    如果你要实现 Statement 重用的话,那就更加复杂了,而且也不能使用 Statement,
    而应使用 PreparedStatement,并且建立 PreparedStatement 池,并且要与 Connection 绑定。可以去参考一下:
    夏昕等编写的《深入浅出 Hibernate》,其中对连接池有相当的介绍。
      

  4.   

    哦,呵呵,谢谢!那我就直接用conn啦,每次获取一个conn好啦!