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