我现在是同连接池来实现,然后自己定义了个方法 public java.util.ArrayList executeQuery(String sqlQueryStmt)
public boolean executeUpdate(String sqlQueryStmt) 做为统一接口,想把所有方法都改成 static的, 但是还没有试过。不过现在已经方便很多了。 userinfo = dbcon.executeQuery(“select * from user”);
java.util.HashMap user=new java.util.HashMap();
for (int i=0;i<userinfo.size();i++ ) {
user=(java.util.HashMap)userinfo.get(i);
%>
用户id<%=user.get("userid")%>
用户名字<%=(String)user.get("username")%>
说明<%=(String)user.get("rolecontent")%>这样操作起来方便多了。不过连接池不听的释放和断开连接,我不知道效率影响大不大。
解决方案 »
- 求助,System.out.println();解释?
- 求最新SCJP题库
- 关于文件的AES加密的难题
- JScrollBar 在JDialog中 为JScrollBar添加AdjustmentListener 不起作用
- java中如何访问不同Jpanel中的控件
- 请问一下,如何实现让java执行某个class下面指定的方法?
- 我想问下如果求前几天的日期?
- 如果1个方法中的参数类型是对象类型,那么这个参数可以接受一个该对象类型的子类的对象吗?
- 高难问题!请教高手!100分。
- 有没有一个方法可以返回每个记录集包含多少个字段?
- 线程疑问
- 高分求教:怎样用JAVA实现"自动调用对应程序打开指定文件"???----急!!!
我看够戗。
最起码的,JDK API中对ResultSet 的说明是:当STATEMENT被CLOSE,那么该ResultSet对象也会被同时关闭。所以你的类,除非是在JDBC实现不符合JDK API规范的前提下才可能运行正常。
还有,没有看到你关闭连接。
其它的暂不作评论了,以免打击你,建议你多看些书吧。如果是针对ORACLE的,那么推荐你一本:《ORACLE JAVA程序设计》
(红皮的,出了一个系列的书,书名我也不是很确定)再说点,任何优化都应该在可测试且知道真正瓶颈的前提下才好做的,
不然做了不如不作。特别是对性能的优化,首先要做的是针对系统的准确测量,找到真正的性能瓶颈。
至少ORACLE是这样。(JDBC的实现其实是关键,所以对不同数据库应该是有区别的)
谢谢您的回复!
首先说明,这里的代码只是部分代码。然后说明一下,这个类工作正常。
我贴一下这个类的完整代码,大家再帮忙看看,谢谢!
package com.strong.data;import java.io.*;
import java.sql.*;
import java.util.Vector;
import java.io.*;
import com.strong.utils.*;/**
* <p>Title: 数据库操作类</p>
* <p>Description: 数据库操作函数</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: 江西思创数码科技公司</p>
* @author 姜晓东
* @version 1.0
*/
public class DataOpt {
/*** 私有变量声明 ***/
private ResultSet resultSet=null;
private Statement statement=null;
private Connection conn=null;
//----------------------------------------------------------------------
/**
* 在构造函数中连接数据库
* @param dbType 数据库类型
* @param userId 用户名
* @param userPwd 口令
*/
public DataOpt() {
try {
conn = ConnectionManager.getConnection();
ConnectionManager.getStats();
}
catch (Exception ex) {
System.err.println("不能连接数据库!" + ex.getMessage());
}
} //----------------------------------------------------------------------
/**
* 执行返回记录集的查询
* @param sqlString SQL查询字符串
* @return 返回ResultSet对象
*/
public ResultSet executeQuery(String sqlString) {
statement = null;
resultSet = null;
try {
statement = conn.createStatement();
resultSet = statement.executeQuery(sqlString);
}
catch (SQLException ex) {
System.err.println("executeQuery()出错:" + ex.getMessage());
}
finally{
try {
if (statement != null) {
statement.close();
statement=null;
}
}
catch (SQLException ex1) {
System.err.println("executeQuery() error!");
}
}
return resultSet;
} //----------------------------------------------------------------------
/**
* 执行插入、更新、删除查询
* @param sqlString
*/
public void executeUpdate(String sqlString) {
statement = null;
try {
statement = conn.createStatement();
statement.executeUpdate(sqlString);
}
catch (SQLException ex) {
System.err.println("executeUpdate()出错" + ex.getMessage());
}
finally{
try {
if (statement != null) {
statement.close();
statement=null;
}
}
catch (SQLException ex1) {
System.err.print("DataOpt.executeUpdate() error!\n"+ex1.getMessage());
}
}
} /**
* 向CLOB写入数据
* @param querySql CLOB字段插入empty_clob()
* @param tableName
* @param keyId
* @param clobField
* @param validateField
* @param validateValue
* @throws SQLException
* @throws IOException
*/
public void setClob(String querySql, String tableName, String keyId,
String clobField, String clobData, String validateField,
String validateValue) throws SQLException, IOException {
try {
resultSet = null;
conn.setAutoCommit(false);
this.executeUpdate(querySql); //执行插入操作,CLOB字段插入empty_clob() resultSet = this.executeQuery("SELECT " + keyId + " FROM " + tableName +
" WHERE " + validateField + "='" +
validateValue + "'");
int curId = (resultSet.next()) ? resultSet.getInt(keyId) : 1; resultSet = this.executeQuery("SELECT " + clobField + " FROM " +
tableName + " WHERE " + keyId + "=" + curId +
" FOR UPDATE");
oracle.sql.CLOB clobText = null;
clobText = (resultSet.next()) ?
(oracle.sql.CLOB) resultSet.getClob(clobField) : null;
Writer writer = clobText.getCharacterOutputStream();
writer.write(clobData);
writer.flush();
writer.close();
conn.commit();
}
catch (SQLException ex) {
System.out.println(ex.getMessage());
}
finally {
try {
resultSet.close();
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
conn.setAutoCommit(true);
}
} /**
* 读取CLOB字段数据
* @param tableName
* @param keyId
* @param clobField
* @param opId
* @return
*/
public String getClob(String tableName, String keyId, String clobField,
String opId) {
String returnString = "";
try {
StringBuffer querySql = new StringBuffer();
querySql.append( "SELECT " ).append( clobField ).append( " FROM " ).append( tableName ).append( " WHERE ") .append(
keyId ).append( "=" ).append( opId);
resultSet = this.executeQuery(querySql.toString());
if (resultSet.next()) {
oracle.jdbc.driver.OracleResultSet oracleResultSet =
(oracle.jdbc.driver.OracleResultSet) resultSet;
oracle.sql.CLOB clob = (oracle.sql.CLOB) oracleResultSet.getClob(1); if (! (clob == null || clob.length() == 0)) {
returnString = clob.getSubString( (long) 1, (int) clob.length());
returnString = StringKit.unFilterHTML(returnString);
}
}
}
catch (SQLException ex) {
System.out.println(ex.getMessage());
}
finally{
try{
resultSet.close();
}catch(SQLException ex){}
}
return returnString;
} /**
* 执行存储过程
* @param procName
* @param params
*/
public void execProc(String procName, String params) {
//构造命令字符串///////////////////////////////////////
String tmp[] = params.split(",");
StringBuffer cmd = new StringBuffer();
StringBuffer tmp2 = new StringBuffer();
StringBuffer tmp3 = new StringBuffer(); //类型
//String tmp3 = ""; //值
cmd.append("{call " + procName + "("); for (int i = 0; i < tmp.length; i++) {
cmd .append( "?,");
/////////////////////////////////////////
String[] tmp1 = tmp[i].split("#");
tmp2 .append( tmp1[0] ).append( ",");
tmp3 .append( tmp1[1] ).append( ",");
}
cmd.substring(0, cmd.length() - 1);
cmd .append( ")}");
tmp2.toString().substring(0, tmp2.length() - 1);
tmp3.toString().substring(0, tmp3.length() - 1);
/////////////////////////////////////////////
String[] _tmp2 = tmp2.toString().split(","); //拆分为数组
String[] _tmp3 = tmp3.toString().split(",");
CallableStatement cstmt = null;
try {
cstmt = conn.prepareCall(cmd.toString());
for (int i = 0; i < _tmp2.length; i++) {
if (_tmp2[i].equals("int")) {
cstmt.setInt(i + 1, Integer.parseInt(_tmp3[i]));
}
else if (_tmp2[i].equals("var")) {
cstmt.setString(i + 1, _tmp3[i]);
}
}
cstmt.execute();
cstmt.close();
}
catch (SQLException ex) {}
catch (NumberFormatException ex) {}
} //----------------------------------------------------------------------
/**
* 清理对象
* @throws SQLException
*/
public void dispose() {
try {
ConnectionManager.returnConnection(conn);
/*System.out.println("成功关闭Statement对象并归还数据库连接!连接数:" +
ConnectionManager.getInstanceNum());*/
ConnectionManager.getStats();
}
catch (SQLException ex) {
System.err.println("连接池错误!" + ex.getMessage());
}
}
}
private static DataOpt instance = null; private DataOpt(){
...
} public static DataOpt getIntance(){
if (instance == null){
instance = new DataOpt();
}
return instance();
}
...}
您好!
非常感谢您的回复!
希望大家讨论一下这里能不能、该不该使用单例模式?谢谢!
Connection 对象可以同时有几个实例共存,不需要是单一实例。
晕!您引述的是《JAVA与模式》P228页内容(附后),能否按您的理解进行说明呢?附:
例子二
问:我的一个系统需要管理与数据库的连接。学习了单例模式后,我发现可以使用一
个单例类包装一个Connection 对象,并在finalize()方法中关闭这个Connection 对象。这样
的话,在这个单例类的实例没有被人引用时,这个finalize()对象就会被调用,因此,
Connection 对象就会被释放。这多妙啊。
答:这样做是不恰当的。除非有单一实例的需求,不然不要使用单例模式。在这里
Connection 对象可以同时有几个实例共存,不需要是单一实例。
单例模式有很多的错误使用案例都与此例子相似,它们都是试图使用单例模式管理共
享资源的生命周期,这是不恰当的。
是的!建立连接以及执行executeQuery需要很大的系统开销,请问DataSouce能带来什么好处呢?
整个类我没有看到CLOSE CONNECTION的语句,
单凭这一点,
这个类就没有价值。具体就不细讲了,可以看下这个帖子的讨论:
http://expert.csdn.net/Expert/topic/2336/2336848.xml?temp=.6394464
里面有我的观点。
这个问题,
每次操作都实例化并不浪费资源,
而且这是必须的,因为有并发访问存在。你知道访问数据库中最大的资源是什么吗?是数据库连接,connection
你不关闭连接,才是真正的资源浪费,你指望垃圾收集帮你收集?
那是不可能的,先不说垃圾收集什么时候开始不确定,就是收集了,也不能替你关闭连接。
如果你使用finalize()方法来关闭,结果是一样的,
因为垃圾收集并不是那么及时的,所以放在finalize()中只能说比你完全不CLOSE好那么一点,不过也就半斤八两。
连接肯定是关闭了的,由于使用了连接池,你没看到这个类有个dispose方法么?里面就是将用完的Connection重新放进连接池的,如下:
/**
* 清理对象
* @throws SQLException
*/
public void dispose() {
try {
ConnectionManager.returnConnection(conn);
/*System.out.println("成功关闭Statement对象并归还数据库连接!连接数:" +
ConnectionManager.getInstanceNum());*/
ConnectionManager.getStats();
}
catch (SQLException ex) {
System.err.println("连接池错误!" + ex.getMessage());
}
}
System.out.println("SQL String is " + sqlQueryStmt);
java.util.ArrayList rows = new java.util.ArrayList();
java.sql.Connection conn = null;
java.sql.Statement stmt = null;
java.sql.ResultSet rs = null;
try {
conn = this.getConnection(10000);
stmt = conn.createStatement();
rs = stmt.executeQuery(sqlQueryStmt);
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while (rs.next()) {
HashMap row = new HashMap();
for (int i = 1; i <= columnCount; i++) {
String cname = rsmd.getColumnName(i);
row.put(cname, rs.getObject(i));
}
rows.add(row);
}
return rows;
}
catch (Exception e) {
System.out.println("查询数据库出错,SQL语句为:" + sqlQueryStmt + "\n错误信息为:" +
e.getMessage());
return null;
}
finally {
try {
rs.close();
stmt.close();
//关闭连接,返回连接
this.freeConnection(conn);
conn = null;
}
catch (Exception e) {
System.out.println("释放连接出错,错误信息为:" + e.getMessage());
// return rows;
}
}
}
最好不要用JDBC-ODBC桥!
请教:
直接返回ResultSet和把结果存放至ArrayList再返回,后者有何优点呢?
我才想到你的关闭操作是在这个类外部操作的,
如果是那样,那么你这个类只能算一个工具类,实现一些通用的操作方法而已,
外部需要重新包装DAO。就你实现的共用的方法来说:
第一、使用STATEMENT,效率很低,不是说编程效率,而是实际数据库访问对SQL的解析和执行,ORACLE的对SQL语句的执行机制决定了的,应该使用PREPAREDSTATEMENT,特别是带参数的语句,不论带的参数是int还是string还是其它什么的。(我只熟悉ORACLE,所以我也就ORACLE说,其它数据库不了解具体ORACLE执行SQL的过程说起来很长,就不细解释了)
第二、看到的一个execProc(String procName, String params)方法使用参数传递,当时参数传递的方式很差,居然用一个STRING,然后在方法中分析STRING来处理,绝对是下下策。而且只支持STRING和INT的设置,还没有返回值,可用性很低,至少要有返回值处理,因为数据库端可能会有业务逻辑错误通过返回值返回,而具有返回操作结果记录的存储过程实在经常用。
第三、异常都被CATCH了,而且有些还什么处理都不作,实在很糟糕这样做。
第四、setClob方法,该方法不管三七二十一,就在处理完成后把AUTOCOMMIT设置为TRUE,
如果外部正在进行事务处理怎么办?(这里,原来我以为你是准备在外部控制事务的,现在看来我的想法有点错误,估计对于事务,你会重新new出CONNECTION来处理)
第五、一些小细节,比如在方法的开头有:
statement = null;
resultSet = null;
这么做基本上没有什么意义,因为你在下面直接就又给相应变量重新赋值了,所以这么做没有必要,可以说完全是白做。最后,我还是不理解:
public ResultSet executeQuery(String sqlString)
这个方法真的可以返回一个可以使用的ResultSet吗?当然,看样子你早用过了,估计是可以,不过JDK API中对RESULTSET和STATEMENT的说明中,明确指出:
When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
不知道你用的是什么JDBC,你依赖的是具体JDBC的不规范实现,这样做感觉很不好。
引用swinging(山不在高)的话:“我才想到你的关闭操作是在这个类外部操作的,”这样操作起来也很不方便的。我是看 jdon上面一篇文章的例子是用的ArrayList的方式来返回,我在外部的操作使用非常方便,就可以完全不关心数据库里的查询函数的具体实现了,
(请看看我顶楼的回复 )
也完全不用去关心数据库的连接和断开连接的问题,外部的操作,仅仅只提交一个SQL语句,然后就可以在返回的ArrayList对得到的结果进行读取操作了。