java 一次初始化一个数据库连接对象并重用它 - jboss
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10598409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
initializing a database connection object once and reusing it - jboss
提问by Ashwin
i am using jboss server and postgresql as the database. Right now I am connecting to the database each time in the servlet like this:
我使用 jboss 服务器和 postgresql 作为数据库。现在我每次都在 servlet 中像这样连接到数据库:
public void doPost(HttpServletRequest req, HttpServletResponse resp)
{
Connection conn =null; // Create connection object
String database = "jbossdb"; // Name of database
String user = "qwerty"; //
String password = "qwerty";
String url = "jdbc:postgresql://localhost:5432/" + database;
ResultSet rs = null;
ResultSetMetaData rsm = null;
ObjectInputStream in=new ObjectInputStream(req.getInputStream());
String input=(String) in.readObject();
String[] s_input=input.split(",");
try{
Class.forName("org.postgresql.Driver").newInstance();
//.newInstance()
} catch(Exception e)
{
System.err.println(e);
}
try{
conn = DriverManager.getConnection(url, user, password);
}catch(SQLException se)
{
System.err.println(se);
}
This code is present in every servet of mine. For each request a new connection object is made. Will this affect performance? Is there any way in jboss where the connection can be initialized only once(possibly on startup) and then passed on to the servlets when required? Should I put it in the init()
method of servlet?
这个代码存在于我的每一个服务中。对于每个请求,都会创建一个新的连接对象。这会影响性能吗?jboss 中是否有任何方法可以使连接仅初始化一次(可能在启动时),然后在需要时传递给 servlet?我应该把它放在init()
servlet的方法中吗?
回答by Jaydee
A much better way of doing this is using a connection pool. You also need to ensure that you close the connections properly (is isn't clear from your code if this is happening, with a pool it still needs to be done). As for storing the connection, that is not really a good idea as your servlet is multithreaded (I learned this the hard way) and you would need to sychronize all accesses which would be a bit of a disaster .
一个更好的方法是使用连接池。您还需要确保正确关闭连接(如果发生这种情况,您的代码中不清楚,仍然需要完成一个池)。至于存储连接,这不是一个好主意,因为您的 servlet 是多线程的(我以艰难的方式了解到这一点)并且您需要同步所有访问,这将是一场灾难。
http://geekexplains.blogspot.co.uk/2008/06/what-is-connection-pooling-why-do-we.html
http://geekexplains.blogspot.co.uk/2008/06/what-is-connection-pooling-why-do-we.html
http://confluence.atlassian.com/display/DOC/Configuring+a+PostgreSQL+Datasource+in+Apache+Tomcat
http://confluence.atlassian.com/display/DOC/Configuring+a+PostgreSQL+Datasource+in+Apache+Tomcat
http://www.devdaily.com/blog/post/java/how-configure-tomcat-dbcp-connection-pool-pooling-postgres
http://www.devdaily.com/blog/post/java/how-configure-tomcat-dbcp-connection-pool-pooling-postgres
--EDIT-- Why not do it in "init()"?
--EDIT-- 为什么不在“init()”中做呢?
Learn about the "life cycle of a servlet".
了解“servlet 的生命周期”。
init() is only called once when the servlet is set up by the container.
init() 仅在容器设置 servlet 时调用一次。
Each request is using the same servlet not a new instance for each request. So init() will not be called for a request.
每个请求都使用相同的 servlet,而不是每个请求的新实例。所以 init() 不会被请求调用。
As each request is processed by the same servlet instance, your code needs to be multithreaded.
由于每个请求都由同一个 servlet 实例处理,因此您的代码需要是多线程的。
回答by Krishan
It is probably not a good solution that you are having here. When you are using servlets in order to do something your application loads, you can have listeners. What you have to do is, first create a class implementing ServletContextListener.
这可能不是您在这里拥有的一个好的解决方案。当您使用 servlet 来执行应用程序加载的某些操作时,您可以拥有侦听器。您需要做的是,首先创建一个实现ServletContextListener的类。
public class ContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
ServletContext context=sce.getServletContext();
String dburl=context.getInitParameter("dbUrl");
String dbusername=context.getInitParameter("dbUserName");
String dbpassword=context.getInitParameter("dbPassword");
DBConnector.createConnection(dburl, dbusername, dbpassword);
System.out.println("Connection Establised.........");
}
public void contextDestroyed(ServletContextEvent sce) {
DBConnector.closeConnection();
}
}
After that you can create another class to create the connection when application loads.
之后,您可以创建另一个类以在应用程序加载时创建连接。
public class DBConnector {
private static Connection con;
public static void createConnection(String dbUrl,String dbusername,String dbPassword){
try {
Class.forName("org.postgresql.Driver");
con=DriverManager.getConnection(dbUrl, dbusername, dbPassword);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static Connection getConnection(){
return con;
}
public static void closeConnection(){
if(con!=null){
try {
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
Then when ever you want to get the db connection you can call the static getConnection method and get it. In order to call your listener class you have to add the listener tags inside the web.xml.
然后,当您想要获取数据库连接时,您可以调用静态 getConnection 方法并获取它。为了调用您的监听器类,您必须在 web.xml 中添加监听器标签。
<context-param>
<param-name>dbUrl</param-name>
<param-value>jdbc:postgresql://localhost:5432/jbossdb</param-value>
</context-param>
<context-param>
<param-name>dbUserName</param-name>
<param-value>qwerty</param-value>
</context-param>
<context-param>
<param-name>dbPassword</param-name>
<param-value>qwerty</param-value>
</context-param>
<listener>
<listener-class>com.icbt.bookstore.listener.ContextListener</listener-class>
</listener>
It is not good practice to hardcode your db usernames and passwords. Instead you can use servlet init parameters in the web.xml as shown.
硬编码您的数据库用户名和密码不是一个好习惯。相反,您可以在 web.xml 中使用 servlet init 参数,如图所示。
Hope, this answers your question.
希望,这回答了你的问题。