3

我有以下方法将某些内容从我的 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 吗?我希望它是在第一次加载类时创建的,并且在整个应用程序范围内都可用?因为会有很多用户进来,我担心这种方法是正确的,还是需要任何其他方法?如果不清楚,请告诉我,我会回来的。

4

2 回答 2

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

在这个网站上有一本很棒的书叫做 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

如果要发送变量,则不得创建另一个实例。您可以通过 2 种方式发送变量:

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;
    }
}
于 2012-05-27T10:26:12.413 回答
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();
于 2013-08-07T12:27:27.290 回答