一般的Java网页编程书籍或者资料里面会介绍Web应用中如何用Java实现访问数据库。从代码上没有太大的问题。但是,真正应用中,需要考虑的情况还很多,现在举例分析一下。
代码一:
1 Connection con = null;
2 Statement stm = null;
3 ResultSet rs = null;
4 String sql = "select * from test";
5 try {
6 Class.forName("org.gjt.mm.mysql.Driver");
7 con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","","");
8 stm = con.createStatement();
9 stm.execute(sql);
10 rs = stm.getResultSet();
11 while(rs.next()){
12 System.out.println(rs.getString(1)+"\t"+rs.getString(2));
13 }//while
14 rs.close();
15 stm.close();
16 con.close();
17 }//try
18 catch (Exception ex) {
19 }//catch
上面的代码从表面上看,在顺利的情况下,运行应该很正常。即使出现问题,也应该捕获并中止了,但隐患就在try{}catch块中。
如果mySql的JDBC驱动加载、与mySql数据库创建连接都正常,但是在执行SQL语句时发生错误,程序自动跳到catch中处理,同时也跳过了关键的三行close()。这种情况下,数据库并不认为已经释放了连接,连接仍然保持到超时才被释放,如果出现这段代码在短时间重复出现并出错,就很容易耗尽数据库连接资源。
如果SQL语句正常,顺利获得了结果集,也并非后面就一定顺利。在结果集的读取或打印中都可能会发生异常,导致资源未能正常关闭。解决方法,在后面追加如下代码:
20 finally{
21 if (rs!=null) {
22 try {
23 rs.close();
24 }
25 catch (Exception ex) {
26 }
27 }//if(rs)
28 if (stm!=null) {
29 try {
30 stm.close();
31 }
32 catch (Exception ex) {
33 }
34 }//if(stm)
35 if (con!=null) {
36 try {
37 con.close();
38 }
39 catch (Exception ex) {
40 }
41 }//if(con)
42 在try{}catch(){}finally{}中,除非前面出现System.exit()语句,无论何种情况都会执行finally{}中的代码。所以在它里面,追加了对资源是否释放进行确认,并对没有释放的资源进行释放。(注:这里只是为了讲解。实际上如果后面还有代码需要访问connection或statement,这里就不用关闭,留在后面来关闭就可以了。)
当然,Web应用做的越大,实际情况就越复杂。一些必要的监测手段是非常重要的。在Oracle等数据库中都有监测数据库连接和释放的应用程序。但是只能知道哪个连接没有释放,不能知道具体哪个类出错的。
这里,向大家推荐Orion(JSP/Sevlet/EJB)容器,虽然这款容器已经没有怎么发展了,但它还是有很多优秀的地方。它是纯Java写的,有自己的控制台程序。最重要的是可以监测Web应用中数据库连接是否正常释放。这款容器可以到www.orionserver.com上面下载,解压后,将JDK\lib目录下的tools.jar拷贝到解压目录,然后双击orion.jar,就启动了,但是以后台方式运行的。可以做这样的一个批处理文件console.bat:
java -jar -Djdbc.connection.debug=true orion.jar –console
用这个批处理来启动orion,启动过程中会有一个窗口弹出,告诉你这个控制台是alpha版,选“是”就可以了。
注意:最好使用java -jar,不要使用javaw -jar,虽然这样会有一个令人讨厌的DOS窗口,但-Djdbc.connection.debug=true参数,就是为了能够在数据资源连接异常时抛给DOS控制台的,没有办法只有用DOS窗口了。
对于数据库连接池的解决方案,几乎除了connection方式不同,其他的都没有什么大的变化。
写得很杂,都搞不清楚大家能否理解,只是希望能够给某些初学者一些帮助。以免不必要的麻烦。