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 回に 1 回コミットします。別の 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 Go to パズル 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

静的ブロックで接続を作成したため、複数のクライアントがクエリを要求すると問題が発生します。その時点で、すべての要求に対して 1 つの接続のみが機能し、マルチスレッドの問題が発生します。スレッド セーフに加えて、接続タイムアウトの問題も示されます。これを避けるには、次のようにコードを書く必要があります..

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 に答える