照书上抄了一个封装JDBC的数据库工具类,没想到用的时候出了很多问题,
它当初使用的环境是JDBC直连的方式,现在我稍加修改换成了数据库连接池,
结果错误百出,查找这些错误耗费了我几天的时间,刚开始报错说:
Statement 对象已关闭,我很奇怪为什么会自动关闭,后来发现是在代码中调用了
下面的stop()方法手动关闭的,于是就将其注释掉了,但是同样的错误依旧,
最后才发现原因:原来开在一个业务逻辑类中我忘了注释stop(),代码执行到此
仍然关闭了Connection和Statement的引用,这个。。这个纯属个人疏忽所致。。。汗!
不过让我不解的是,将代码中所有的stop()方法都注释掉之后,就再也没问题了,可转念一想,这些连接难道都不需要关闭吗?那这个stop()方法岂不是没用处了啊,那还写它干吗?
跟踪调试过程中发现,一旦执行stop(),就会使conn==null,然后第二次调用DataStore ds=DataStore.getInstance();时只是判断static DataStore db 是否为 null;若为空再新建一个Connection,但事实上db并不为空,于是在以后的代码中调用conn就会报NullPointEsception,调用stmt就会报 已经关闭的Exception.
我知道问题一定出在这个private static DataStore db 上,可又不知道怎么修改,总不能在stop()中吧db也=null了吧?但是如果不使用stop()释放数据库资源,那么我的连接池又有什么用那?在并发处理时如何解决,总不能靠那一个Connection连接吧??
package org.database;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.sql.DataSource;
/* 封装JDBC的主要数据库操作:CRUD与事务操作,实现数据库访问层与业务逻辑层的分离 */
/* 使用举例:
* 1.插入,删除,更新
* String sql="delete from uesr";
* 先获取数据库访问实例
* DataStore ds=DataStore.getInstance();
* try{
* ds.execute(sql);
* }catch(Exception e){
* ....}
* 2.读取操作
* String sql="select * from user";
* 获取实例
* DataStore ds=DataStore.getInstance();
* try{
* ResultSet rs=ds.read(sql);
* ...
* }catch(Exception e){
* ....}
* 3.事务操作
* DataStore ds=DataStore.getInstance();
* ds.beginTransaction();
* String sql_1="delete * from user";
* String sql_2="insert into user values('username','password')";
* try{
* ds.execute(sql_1);
* ds.execute(sql_2);
* }catch(Exception e){
* ds.ErrorOccur();
* }
* ds.commitTransaction();
*/
public class DataStore
{
// 静态工厂模式
private static DataStore db = null;
// 数据库连接对象
private static Connection conn = null;
private Statement stmt = null;
private boolean haddErrors = false;
// 构造函数
private DataStore() throws Exception
{
if (conn == null)
{
// 从数据源获得连接
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx
.lookup("java:comp/env/jdbc/webmail");
conn = ds.getConnection();
stmt = conn.createStatement();
}
}
// 取得DataStore实例, 工厂方法
public static DataStore getInstance()
{
if (db == null)
{
try
{
db = new DataStore();
}
catch (Exception e)
{
conn = null;
// 日志处理
System.out.println("----取得DataStore实例出错---");
e.printStackTrace();
}
}
return db;
}
// 发起事务
public void beginTransaction() throws SQLException
{
//System.out.println(conn.isClosed());
if (conn != null) // 不是必需的,非问题关键所在
conn.setAutoCommit(false);// 应用JDBC事务,设置为非自动提交
}
// 执行事务
public void commitTransaction() throws SQLException
{
if (!haddErrors)
{
conn.commit();
}
else
{
conn.rollback();
haddErrors = false;
}
haddErrors = false;
conn.setAutoCommit(true);
}
// 标记出错
public void ErrorOccur()
{
haddErrors = true;
}
// 执行插入,删除和修改操作
synchronized public void execute(String sql) throws SQLException
{
// if (conn!= null) stmt = conn.createStatement();
if (stmt != null) stmt.executeUpdate(sql);
else
{
// 日志处理
System.out.println("数据库插入出错!");
}
}
// 查询操作
synchronized public ResultSet read(String sql) throws SQLException
{
if (stmt != null)
{
ResultSet tmp = null;
tmp = stmt.executeQuery(sql);
return tmp;
}
else
{
return null;
}
}
// 查询个数操作
synchronized public int readCount(String sql) throws SQLException
{
int nCount = 0;
try
{
if (stmt != null)
{
ResultSet tmp = null;
tmp = stmt.executeQuery(sql);
if (tmp != null && tmp.next()) nCount = tmp.getInt(1);
else
nCount = 0;
}
else
nCount = 0;
}
catch (SQLException e)
{
return nCount;
}
return nCount;
}
// 终止数据库连接
synchronized public void stop()
{
try
{
if (stmt != null)
{
stmt.close();
}
if (conn != null)
{
conn.close();
}
}
catch (Exception e)
{
// 记录日志
System.out.println("数据库关闭出错!");
e.printStackTrace();
}
finally
{
conn = null;
}
}
}