Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JSP中的单件,如何正确整理上下?_Java_Jsp_Destructor - Fatal编程技术网

Java JSP中的单件,如何正确整理上下?

Java JSP中的单件,如何正确整理上下?,java,jsp,destructor,Java,Jsp,Destructor,我刚刚开始学习jsp,我的问题是——当我有一个单例类时,我该如何整理它 特别是: public class DBConnection { private static Connection connection = null; private static Statement statement = null; public static ResultSet executeQuery(String query){ if (connection == null) { /*in

我刚刚开始学习jsp,我的问题是——当我有一个单例类时,我该如何整理它

特别是:

public class DBConnection {
  private static Connection connection = null;
  private static Statement statement = null;

  public static ResultSet executeQuery(String query){
    if (connection == null) { /*initConnection*/ }
    if (statement == null) { /*initStatement*/ }

    // do some stuff
  }
}
现在,我在几个页面中使用这个类从jdbc获得结果。但是,我最终需要调用
语句.close()
连接。关闭()-我应该什么时候打电话


我使用的是singleton,因为每当我需要进行查询时,反复调用与数据库的连接是错误的。

我将向该类添加两个方法:

public static void open() throws SomeException;
public static void close() throws SomeException;
然后你的呼叫代码看起来像这样{

try {
    DBConnection.open();
    ... code to use the connection one or more times ...
} finally {
    DBConnection.close();
}
将所有数据库调用都封装在其中,它将负责关闭是否引发异常

当然,这与定期上课没什么不同,我可以推荐:

try {
    DBConnection conn = new DBConnection();
    conn.open();

    ... all the code to use the database (but you pass 'conn' around) ...

} finally {
    conn.close();
}
您可能需要查看
java.lang.AutoCloseable
java.io.Closeable
以了解这是否对您有所帮助

2

如果要在页面加载时保持打开状态,则没有任何地方可以放置
try…finally
之类的内容,以便在servlet关闭或服务器关闭时打开并关闭它

如果要让它保持打开状态,则需要确保并添加代码,以验证它在不查看时没有关闭。例如,一个短暂的网络故障可能会使它关闭。在这种情况下,需要在它关闭时重新打开它。否则,从该点开始的所有数据库访问都将失败

您可能想了解数据库池的概念。Apache有一个——DBCP。Tomcat有自己的数据库池,这很好。其他容器,如JBOSS、WebSphere和WebLogic都有。Spring框架可以使用两个。它所做的是管理一个或多个数据库连接。您的代码要求它连接,然后返回一个打开的连接,除非没有可用的连接,否则它会打开一个并返回它。当你的代码通过它时,你调用
close
,但它没有真正关闭连接,它只是将它返回到池中


通常,您可以将池配置为检查关闭的连接,并在需要时重新打开。

必须始终关闭
连接,并且在为所需操作执行所有数据库语句后关闭。两个示例:

案例1:必须向用户显示根据数据库中的条件筛选的产品列表。解决方案:获取连接,使用筛选条件检索产品列表,关闭连接

案例2:客户选择其中一些产品并更新最低库存以获取警报并重新进货。解决方案:获取连接,更新所有产品,关闭连接

基于这些案例,我们可以学到很多东西:

  • 在打开/维护单个连接时,可以执行多条语句
  • 该连接应仅在使用它的块中有效。在此之前或之后不应有效
  • 这两种情况都可能同时发生,因为它们处于多线程环境中。因此,单个数据库连接不能同时供两个线程使用,以避免结果问题。例如,用户a搜索类别为Foo的产品,用户B搜索类别栏中的产品,您不希望向用户A显示类别栏中的产品
  • 从最后一句话开始,每个数据库操作(或一组类似的操作,如案例2)都应该在一个原子操作中处理。为了确保这一点,连接不能存储在单例对象中,而必须仅在所使用的方法中有效
因此:

  • 不要将
    连接
    语句
    结果集
    或其他JDBC资源声明为
    静态
    。它只会失败。相反,只将
    连接
    声明为
    数据库连接
    类的字段。让每个方法决定处理每一个
    语句(或
    PreparedStatement
    )和
    ResultSet
    以及特定的JDBC资源
  • 由于必须在连接使用后关闭该连接,因此再添加两个方法:
    void open()
    void close()
    。这些方法将处理数据库连接检索和关闭该连接
  • 另外,由于
    DBConnection
    看起来像是
    Connection
    类和数据库连接操作的包装类,我建议至少还有三种方法:
    void setAutoCommit(boolean autoCommit)
    void commit()
    void rollback()
    。这些方法将分别为和的普通包装
然后可以通过以下方式使用该类:

public List<Product> getProducts(String categoryName) {
    String sql = "SELECT id, name FROM Product WHERE categoryName = ?";
    List<Product> productList = new ArrayList<Product>();
    DBConnection dbConnection = new DBConnection();
    try {
        dbConnection.open();
        ResultSet resultSet = dbConnection.executeSelect(sql, categoryName); //execute select and apply parameters
        //fill productList...
    } catch (Exception e) {
        //always handle your exceptions
        ...
    } finally {
        //don't forget to also close other resources here like ResultSet...
        //always close the connection
        dbConnection.close();
    }
}
public List getProducts(字符串categoryName){
String sql=“从产品中选择id、名称,其中categoryName=?”;
List productList=new ArrayList();
DBConnection DBConnection=新的DBConnection();
试一试{
dbConnection.open();
ResultSet ResultSet=dbConnection.executeSelect(sql,categoryName);//执行select和apply参数
//填写产品列表。。。
}捕获(例外e){
//始终处理您的异常
...
}最后{
//不要忘记关闭其他资源,如ResultSet。。。
//始终关闭连接
dbConnection.close();
}
}
请注意,在此示例中,
PreparedStatement
不在
getProducts
方法中,它将是
executeSelect
方法的局部变量

补充说明:

  • 在应用服务器中工作时,不应天真地打开连接,例如使用
    <Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource" 
        maxActive="10" maxIdle="2" maxWait="20000" 
        driverClassName="com.mysql.jdbc.Driver" 
        username="myuser" password="mypwd" 
        url="jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=utf8"
        validationQuery="SELECT 1" />
    
    import java.sql.*;
    import javax.sql.DataSource;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    
    public class DB {
    
    public static Connection createConnection() throws SQLException {
        try {
            Context ctx = new InitialContext();
            DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mydb");
            return ds.getConnection();
        } catch (SQLException ex) {
            throw ex;
        } catch (Exception ex) {
            SQLException sqex = new SQLException(ex.getMessage());
            sqex.initCause(ex);
            throw sqex;
        }
    }
    
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
           if (rs != null) try { rs.close(); } catch (Exception e) { }
           if (stmt != null) try { stmt.close(); } catch (Exception e) { }
           if (conn != null) try { conn.close(); } catch (Exception e) { }
    }
    
    public static void close(ResultSet rs, boolean closeStmtAndConn) {
           if (rs==null) return;
           try {
              Statement stmt = rs.getStatement();
              close(rs, stmt, stmt!=null ? stmt.getConnection() : null);
           } catch (Exception ex) { }
    }
    
    }
    
    public List<MyBean> getBeans() throws SQLException {
        List<MyBean> list = new ArrayList<MyBean>();
        ResultSet rs=null;
        try {
            Connection con = DB.createConnection();
            String sql = "Select * from beantable where typeid=?";
            PreparedStatement stmt = con.prepareStatement(sql, Statement.NO_GENERATED_KEYS);
            stmt.setInt(1, 101);
            rs = stmt.executeQuery();
            while(rs.next()
                list.add( createBean(rs) );
        } finally {
            DB.close(rs, true); // or DB.close(rs, stmt, conn);
        }
        return list;
    }
    
    private MyBean createBean(ResultSet rs) throws SQLException {
        MyBean bean = new MyBean();
        bean.setId( rs.getLong("id") );
        bean.setName( rs.getString("name" );
        bean.setTypeId( rs.getInt("typeid") );
        return bean;
    }