【问题标题】:what is the best practice to close connection when dealing with jdbc处理 jdbc 时关闭连接的最佳做法是什么
【发布时间】:2017-08-08 18:54:48
【问题描述】:

我使用prepareStatement() 来防止sql 注入。我现在遇到的问题是,使用下面的方法,我可以执行getConnection().prepareStatement() 然后构建我的查询,但我需要尝试捕获对getConnection() 的每次调用并在finally 块中关闭它。 createStatement().execute() 似乎更好,因为我可以让客户端传入查询然后在一个地方处理 try-catch-finally,但它不会阻止 sql 注入。通常最好的做法是什么?或者有没有其他方法来构建可以防止sql注入的查询?

private static Connection getConnection() throws SQLException, URISyntaxException {
    URI dbUri = new URI(System.getenv("DATABASE_URL"));

    String username = dbUri.getUserInfo().split(":")[0];
    String password = dbUri.getUserInfo().split(":")[1];
    String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + dbUri.getPath();

    return DriverManager.getConnection(dbUrl, username, password);
}

【问题讨论】:

  • 您应该使用经过充分验证的连接池,而不是创建自己的连接池。检查连接,将其传递给数据访问对象,在 finally 块中关闭方法范围内的所有其他 JDBC 资源,并将连接返回到池中
  • @duffymo 我不太明白。这是我第一次在服务器端编写 Java。你能提供一些例子吗
  • 您会将应用程序部署到什么位置?雄猫?弹簧靴?老板娘?所有都内置了连接池。我建议使用它们。
  • @duffymo Tomcat。谢谢。让我谷歌一下
  • 必须自己关闭所有资源(Connection、Statement、ResultSet)会导致很多容易出错的样板代码。所以你绝对应该看看 Apache Commons DbUtils 或 Spring JDBC 来做到这一点。

标签: java jdbc


【解决方案1】:

我会使用连接池而不是每次都创建连接并关闭。

我们应该遵循几个步骤来使用 tomcat 服务器创建连接池

步骤-1。使用数据库连接详细信息更新 TOMCAT_ROOT_DIR\conf\server.xml 文件,如下所示:

<?xml version='1.0' encoding='utf-8'?>
...
  <GlobalNamingResources>
    ...
    <Resource name="jdbc/JCGExampleDB" 
              global="jdbc/JCGExampleDB"
              factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
              auth="Container"
              type="javax.sql.DataSource"              
              username="test"
              password="test"
              driverClassName="com.mysql.jdbc.Driver"
              description="JCG Example MySQL database."
              url="jdbc:mysql://localhost:3306/JCGExampleDB"
              maxTotal="10"
              maxIdle="10"
              maxWaitMillis="10000"
              removeAbandonedTimeout="300"            
              defaultAutoCommit="true" />
     ...
  </GlobalNamingResources>

步骤-2: 使用 Spring 的 JdbcTemplate - 您可以编写数据库连接实用程序类并获取连接,如下所示(此步骤可以通过多种方式完成......如 context.xml 文件或 web.xml 文件或如下所示)

@Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }

    @Bean
    public DataSource dataSource() {
        DataSource dataSource = new com.mchange.v2.c3p0.ComboPooledDataSource();
        try {
            JndiTemplate jndiTemplate = new JndiTemplate();
            dataSource = (DataSource)jndiTemplate.lookup("java:comp/env/jdbc/JCGExampleDB");
            } catch (NamingException e) {
            log.error("Unable to configure datasource: " + e.getStackTrace());
        }
        return dataSource;
    }

编辑1: 使用 Singleton 类 - 没有 JdbcTemplate:您可以在需要时从 Singleton 类获取连接。

public class DatabaseConnectionManager {

    DataSource ds;

    public void init() {
        InitialContext initialContext = new InitialContext();
        ds = (javax.sql.DataSource)initialContext.lookup("jdbc/JCGExampleDB");
    }

    public Connection getConnection() {
        if(ds == null) init();

        return ds.getConnection();
    }
}

希望这会有所帮助...

【讨论】:

  • 我喜欢你对 JdbcTemplate 的建议,但应该指出的是,只有在 OP 使用 Spring 时才有意义。
  • 我没有使用 Spring。而且我实际上不明白在您的示例中如何正确关闭连接。我是否还需要在每次通话时手动关闭它
  • @user1865027 - 我在不使用 Spring 的情况下更新了我的答案。如果您使用连接池,则池将根据您在 标记中提到的参数来处理打开和关闭连接。
  • @K.S 谢谢。我已经测试了连接池。我仍然需要关闭。我不认为我可以避免它? mentioned here
  • @user1865027 - 是的,如果您使用 getConnection() 从数据源获取连接,您应该负责关闭资源。但是不建议在外部通过 getConnection() 弄乱数据源。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2019-08-16
相关资源
最近更新 更多