连接范围静态变量在整个应用程序的静态方法中?

时间:2012-05-27 09:50:22

标签: java jdbc

我正在使用以下方法将某些内容从我的Java应用程序记录到Oracle DB。

Package com.util.dblog;
public class DBLog {

static Connection con = null;
static PreparedStatement stmt = null;

static { 
 try{
      DBConnectionHelper connHelper = DBConnectionHelper.createInstance();
    con=connHelper.getConnection("ds"); //Getting connection from connection pool
    con.setAutoCommit(false);
    }
catch(Exception e)
{}  
       } 

public static void logmethod1(String param1, String param2) { 

if (con == null || con.isClosed()) {
 DBConnectionHelper connHelper = DBConnectionHelper.createInstance();
    con=connHelper.getConnection("ds");
    con.setAutoCommit(false);
}

String SQL_PREP_INSERT = "INSERT INTO tableA (LOG_ID,USER_ID,EXEC_TIME) VALUES"             + " (logid_seq.nextval, ?, ?)"; 
stmt = con.prepareStatement(SQL_PREP_INSERT); 
stmt.execute();
stmt.close();
}

public static void logmethod2(String param1, String param2, String param3) { 

if (con == null || con.isClosed()) {
 DBConnectionHelper connHelper = DBConnectionHelper.createInstance();
    con=connHelper.getConnection("ds");
    con.setAutoCommit(false);
}

...
...
}

public saveCon() {
con.commit();
}
public closeCon() {
   con.close();
}

} //End of DBLog class

From my Java application class, I am calling as follows,

import com.util.dblog;
public class myApp{
DBLog.logmethod1(param1, param2);
....
DBLog.logmethod2(param1, param2, param3);
...
} //End of myApp class

我在Filter类中的请求级别调用saveCon(),在sessionListener类的destroy()方法中调用closeCon()。而不是在logmethod1和logmethod2中编写连接对象,我这样做只是为了减少提交频率。在我的应用程序中,这种方法将被调用大约5-10次。因此,我将每次提交10次,而不是每次请求10次。假设有另一个http请求,一旦插入10个日志,将会有另一个提交。最后,一旦会话即将被销毁,我将关闭连接。

现在我遇到的问题是,在DBLog类的静态块中创建的连接对象“con”是否可用于静态方法logmethod1和logmethod2? 我希望它是在首次加载类时创建的,并且可以在整个应用程序范围内使用?  因为会有很多用户进来,我担心这种方法是否正确,还是需要任何其他方法? 如果不清楚请告诉我,我会回来。

2 个答案:

答案 0 :(得分:1)

static {}块将在您的方法之前调用,但以这种方式使用您的类是个坏主意。当您可以用经典结构替换静态结构时,请避免使用静态结构。您可以将所有变量和方法更改为非静态,阻止static {}更改为构造函数,您的应用程序将类似于:

import com.util.dblog;
public class myApp{

    DBLog log = new DBLog();

    log.logmethod1(param1, param2);
    log.logmethod2(param1, param2, param3);

} //End of myApp class

这篇site有一本名为Java Puzzlers的好书,我建议你阅读它。 它有一个与您的问题相关的小章节,大约需要3分钟阅读。

Java Puzzlers转到拼图5:比生命更大

我认为你的程序会正常工作。

有一种没有静态块的替代方案:

Package com.util.dblog;
public class DBLog {

Connection con = null;
PreparedStatement stmt = null;

public DBLog () {
    init();
}

private void init() {
    try {
        DBConnectionHelper connHelper = DBConnectionHelper.createInstance();
        con=connHelper.getConnection("ds"); //Getting connection from connection pool
        con.setAutoCommit(false);
    } catch(Exception e) {}  
}

public void logmethod1(String param1, String param2) { 

    if (con == null || con.isClosed()) {
        init();
    }

    String SQL_PREP_INSERT = "INSERT INTO tableA (LOG_ID,USER_ID,EXEC_TIME) VALUES"             + " (logid_seq.nextval, ?, ?)"; 
    stmt = con.prepareStatement(SQL_PREP_INSERT); 
    stmt.execute();
    stmt.close();
}

public void logmethod2(String param1, String param2, String param3) { 

    if (con == null || con.isClosed()) {
        init();
    }
    ...
    ...
}

public void voidsaveCon() {
    con.commit();
}
public void closeCon() {
    con.close();
}

} //End of DBLog class

From my Java application class, I am calling as follows,

import com.util.dblog;
public class myApp {

    ...
    // in some method
    DBLog log = new DBLog();
    log.logmethod1(param1, param2);
    ....
    log.logmethod2(param1, param2, param3);
    ...

} //End of myApp class

如果要发送变量,则不得创建其他实例。您可以通过两种方式发送变量:

SomeAnotherClass {

    // after initialize you can use this log, this log is same as in myApp class
    DBLog log;

    // 1 way: by sending to constructor
    public SomeAnotherClass(DBLog log) {
        this.log = log;
    }

    // 2 way: by calling set method
    public void setLog(DBLog log) {
        this.log = log;
    }
}

答案 1 :(得分:0)

当你在静态块中建立连接时,它会在多个时产生问题     客户端将请求任何查询,那时只有一个连接将适用于它将产生问题的所有请求     多线程。除了线程安全性,它还将显示连接超时的问题。         为了避免这种情况,你应该像这样写代码。

public class DB_Connector {        
    public Connection connection = null;
    public Statement stmt;
    static Properties prop = null;
    public DB_Connector() {
        System.out.println("-------- MySQL JDBC Connection Testing ------------");
        prop = new Properties();
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/" + <db name>,
                    "root", <password>);
            stmt = connection.createStatement();
        } catch (SQLException e) {
            System.out.println("Connection Failed! Check output console");
            e.printStackTrace();

        }

        if (connection != null) {
            System.out.println("You made it, take control your database now!");
        } else {
            System.out.println("Failed to make connection!");
        }

    }

    public ResultSet queryResult(String Query) {
        ResultSet rst = null;
        try {
            rst = stmt.executeQuery(Query);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return rst;
    }

    public int queryCount(String Query) {
        int count = 0;
        try {
            count = stmt.executeUpdate(Query);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return count;
    }
    public void closeConnection()
    {
        try {
            connection.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这是一种处理任何查询的安全方法。您的电话应按此顺序

   DB_Connector db=new DB_Connector();
    db.queryResult(query);
    db.queryCount(query);
    db.closeConnection();