我的 Web 应用程序中 C3P0 的这种实现是否正确?这种实施的优缺点是什么?
Do this implimentation of C3P0 in my web application is correct? What are the pros and cons of this implimentation?
我需要在使用 Servlet 和 JSP 页面的 Web 应用程序中实现连接池。我不希望在服务器中的所有应用程序中使用连接池,而是希望在所有 servlet 中实现连接池。
我有一个 C3P0 的工作实现,但我不知道这是否是正确的方法,并且这样做会产生预期的结果。
以下是我的实现
有一个数据源文件 C3P0 实现到 return 连接。
连接将在 servelet init 方法上检索并在 destroy 方法上关闭。
- 这种实施方式是否会产生预期的结果?
- 我必须在销毁中关闭连接吗?
- 实现 servlet 应用程序连接池的其他方法有哪些?
- 我喜欢将所有与数据库相关的操作移动到单独的 类,在这种情况下,我必须处理哪些事情,我是否必须在 servlet 中获取连接并传递给数据库方法那案子呢?
- 请给出当前实施的优缺点
请在下面找到我的连接池实现
return连接的数据源文件和使用连接的 Servelt
数据源文件
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSource {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://dburl/dbName";
// Database credentials
static final String USER = "username";
static final String PASS = "password";
private static DataSource datasource;
private ComboPooledDataSource cpds;
private DataSource() throws IOException, SQLException, PropertyVetoException {
cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver"); //loads the jdbc driver
cpds.setJdbcUrl(DB_URL);
cpds.setUser(USER);
cpds.setPassword(PASS);
// the settings below are optional -- c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
cpds.setMaxStatements(180);
}
public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException {
if (datasource == null) {
datasource = new DataSource();
return datasource;
} else {
return datasource;
}
}
public Connection getConnection() throws SQLException {
return this.cpds.getConnection();
}
}
Servlet
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ConnectionTest
*/
@WebServlet("/ConnectionTest")
public class ConnectionTest extends HttpServlet {
Connection connection = null;
Statement statement = null;
@Override
public void init() throws ServletException {
super.init();
try {
connection = DataSource.getInstance().getConnection();
} catch (PropertyVetoException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<h1> Hi</h1>");
ResultSet resultSet = null;
try {
statement = connection.createStatement();
resultSet = statement
.executeQuery("SELECT VehicleRegistration FROM Registration");
while (resultSet.next()) {
String first = resultSet.getString("VehicleRegistration");
// Display values
out.println("<h1> " + first + "</h1>");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (resultSet != null)
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (statement != null)
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Override
public void destroy() {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
super.destroy();
}
}
我欢迎所有有助于我改进此代码的建议,即使它太小或太大
提前感谢大家
所以,这是可以改进的。
您的 Servlet 应该获取对 init(...)
中 DataSource 的引用,而不是在 Servlet 的生命周期内保留未完成的 Connection 对象。 Connection
对象应根据需要从连接池数据源获取,而不是长时间保持打开状态。您的 doGet(...)
方法应该获取 Connection(这会很快,因为它已经在池中了!),然后注意在其 finally 块中对 Connection 调用 close()
。
更改此设置非常重要。除了让 Connection 永远保持打开状态的恶心和资源使用不佳之外,在您当前的体系结构下,对 Servlet 的同时请求将在同一个 Connection 上同时运行,这可能导致意外和不正确的行为,特别是如果您的 webapp 中有 servlets利用事务(大多数重要的应用程序必须如此)。
您的数据源class 似乎不是特别有用。为什么不直接构造 c3p0 DataSource 而不是使用 getConnection()
方法定义一种新的对象。我认为您的动机可能只是让静态成员 datasource
成为一个真正的数据源。但是如果你想将数据源存储为静态成员,你可以在任何地方这样做,没有必要包装实际的数据源。
不过,在 JavaEE Web 应用程序中保存连接池支持的数据源的最佳位置不是作为静态成员。更好的方法是在 ServletContextListener
、contextInitialized(...)
中构建数据源,并将数据源存储在应用程序范围内。在 contextDestroyed(...)
中调用 close()
c3p0 ComboPooledDataSource
,并将其从应用程序范围中删除。
我需要在使用 Servlet 和 JSP 页面的 Web 应用程序中实现连接池。我不希望在服务器中的所有应用程序中使用连接池,而是希望在所有 servlet 中实现连接池。
我有一个 C3P0 的工作实现,但我不知道这是否是正确的方法,并且这样做会产生预期的结果。
以下是我的实现 有一个数据源文件 C3P0 实现到 return 连接。 连接将在 servelet init 方法上检索并在 destroy 方法上关闭。
- 这种实施方式是否会产生预期的结果?
- 我必须在销毁中关闭连接吗?
- 实现 servlet 应用程序连接池的其他方法有哪些?
- 我喜欢将所有与数据库相关的操作移动到单独的 类,在这种情况下,我必须处理哪些事情,我是否必须在 servlet 中获取连接并传递给数据库方法那案子呢?
- 请给出当前实施的优缺点
请在下面找到我的连接池实现
return连接的数据源文件和使用连接的 Servelt
数据源文件
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSource {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://dburl/dbName";
// Database credentials
static final String USER = "username";
static final String PASS = "password";
private static DataSource datasource;
private ComboPooledDataSource cpds;
private DataSource() throws IOException, SQLException, PropertyVetoException {
cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver"); //loads the jdbc driver
cpds.setJdbcUrl(DB_URL);
cpds.setUser(USER);
cpds.setPassword(PASS);
// the settings below are optional -- c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
cpds.setMaxStatements(180);
}
public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException {
if (datasource == null) {
datasource = new DataSource();
return datasource;
} else {
return datasource;
}
}
public Connection getConnection() throws SQLException {
return this.cpds.getConnection();
}
}
Servlet
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ConnectionTest
*/
@WebServlet("/ConnectionTest")
public class ConnectionTest extends HttpServlet {
Connection connection = null;
Statement statement = null;
@Override
public void init() throws ServletException {
super.init();
try {
connection = DataSource.getInstance().getConnection();
} catch (PropertyVetoException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<h1> Hi</h1>");
ResultSet resultSet = null;
try {
statement = connection.createStatement();
resultSet = statement
.executeQuery("SELECT VehicleRegistration FROM Registration");
while (resultSet.next()) {
String first = resultSet.getString("VehicleRegistration");
// Display values
out.println("<h1> " + first + "</h1>");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (resultSet != null)
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (statement != null)
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Override
public void destroy() {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
super.destroy();
}
}
我欢迎所有有助于我改进此代码的建议,即使它太小或太大
提前感谢大家
所以,这是可以改进的。
您的 Servlet 应该获取对 init(...)
中 DataSource 的引用,而不是在 Servlet 的生命周期内保留未完成的 Connection 对象。 Connection
对象应根据需要从连接池数据源获取,而不是长时间保持打开状态。您的 doGet(...)
方法应该获取 Connection(这会很快,因为它已经在池中了!),然后注意在其 finally 块中对 Connection 调用 close()
。
更改此设置非常重要。除了让 Connection 永远保持打开状态的恶心和资源使用不佳之外,在您当前的体系结构下,对 Servlet 的同时请求将在同一个 Connection 上同时运行,这可能导致意外和不正确的行为,特别是如果您的 webapp 中有 servlets利用事务(大多数重要的应用程序必须如此)。
您的数据源class 似乎不是特别有用。为什么不直接构造 c3p0 DataSource 而不是使用 getConnection()
方法定义一种新的对象。我认为您的动机可能只是让静态成员 datasource
成为一个真正的数据源。但是如果你想将数据源存储为静态成员,你可以在任何地方这样做,没有必要包装实际的数据源。
不过,在 JavaEE Web 应用程序中保存连接池支持的数据源的最佳位置不是作为静态成员。更好的方法是在 ServletContextListener
、contextInitialized(...)
中构建数据源,并将数据源存储在应用程序范围内。在 contextDestroyed(...)
中调用 close()
c3p0 ComboPooledDataSource
,并将其从应用程序范围中删除。