彭老师帮看下我自己封装了个JDBC的通用查询,更新函数有没有什么问题。

函数功能实现通用的增删改查,这个是第一版,还需要加的功能很多,希望把问题在萌芽阶段就找出来。


public class DBJdbcRunners {
private static Log log = LogFactory.getLog(DBJdbcRunners.class);
private boolean autoCommit;
Connection connection = null;

public DBJdbcRunners()throws SQLException{
autoCommit = true;
try {
connection = DBUtils.getConnection();
} catch (SQLException e) {
throw new SQLException();
}
}
public void begintx()throws SQLException{
autoCommit = false;
if (connection != null){
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
throw new SQLException();
}
}
}
public void committx()throws SQLException{
autoCommit = false;
if (connection != null){
try {
connection.commit();
connection.setAutoCommit(true);
autoCommit = true;
} catch (SQLException e) {
log.equals("committx exception is ->["+e+"]");
throw new SQLException();
}finally{
DBUtils.closeConnection(connection);
}
}
}

public int executeUpdate (String sql) throws SQLException,
InputIllegalException
{
Statement statement = null;
try
{

statement = connection.createStatement();
int i = statement.executeUpdate(sql);
return i;
}catch( SQLException e){
log.error(
"error sql is-->["+sql+"]");
log.error(e);
if(!autoCommit){
try{
connection.rollback();
}catch(SQLException ex){
log.error(ex);
}
}
throw new SQLException();
}
finally{
DBUtils.closeStatement(statement);
if(autoCommit){
DBUtils.closeConnection(connection);
}
}
}


public void executeQuery (
String sql,boolean isgetTotalNum)
throws SQLException,InputIllegalException{

Statement statement = null;
PreparedStatement p_statement = null;
ResultSet rs = null;
if(sql == null){
throw new InputIllegalException(
"in executeQuery function" +
"sql is null");
}
try{
if(isgetTotalNum){
statement = connection.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
}else{
statement = connection.createStatement();
}
rs = statement.executeQuery(sql);
if(isgetTotalNum){
rs.last();
log.debug(
"total row num is-->["+rs.getRow()+"]");
rs.first();
}
ResultSetMetaData rsmd = rs.getMetaData();
int numCols = rsmd.getColumnCount();
log.debug(
"column num is-->["+rsmd.getColumnCount()+"]");

while(rs.next()){
for(int i=1;i<=numCols;i++){
System.out.print(
"column "+i+" is-->["+rs.getString(i)+"]");
}
System.out.print(
"\n");
}
}catch( SQLException e){
log.error(
"error sql is-->["+sql+"]");
log.error(
"[ex in executeQuery function]-->["+e+"]");
if(!autoCommit){
try{
if(log.isDebugEnabled()){
log.debug(
"[in executeQuery function rollback]");
}
connection.rollback();
}catch(SQLException ex){
log.error(ex);
}
}
throw new SQLException();
}
finally{
DBUtils.closeResultSet(rs);
DBUtils.closeStatement(statement);
if(autoCommit){
DBUtils.closeConnection(connection);
}
}

}

}



public class testDBQuery {
private static Log log = LogFactory.getLog(testDBQuery.class);
public static void main(String[] args) {
DBJdbcRunners query = null;
try { query.begintx();
query.executeUpdate("insert into user (id,name) values(9001,'wgm')");
query.executeQuery(
"select id, name from user order by id",true);
query.committx();
} catch (Exception e) {
//System.out.print(rowSet.print());
e.printStackTrace();
}
}

}

以上在MYSQL数据库,INFORMIX数据库上都已经测试过,支持事物。
查询结果正确。
说明在DBJdbcRunners中DBUtils.getConnection();
DBUtils.closeResultSet(rs); DBUtils.closeStatement(statement); DBUtils.closeConnection(connection);
是写的一个通用方法DBUtils,管理连接,结果集和statement。
但我不知道这种调用方式会不会有其他的问题,所以请大家帮我参考下。
===========================
另外我在Jdon发帖子的时候,老是要重新登陆,我不得不复制写下东西。可能一个原因是SESSION设置的失效时间太短,希望管理员解决下。



public class testDBQuery {
private static Log log = LogFactory.getLog(testDBQuery.class);
public static void main(String[] args) {
DBJdbcRunners query = null;
try { query.begintx();
query.executeUpdate("insert into user (id,name) values(9001,'wgm')");
query.executeQuery(
"select id, name from user order by id",true);
query.committx();
} catch (Exception e) {
//System.out.print(rowSet.print());
e.printStackTrace();
}
}

}

以上在MYSQL数据库,INFORMIX数据库上都已经测试过,支持事物。
查询结果正确。
说明在DBJdbcRunners中DBUtils.getConnection();
DBUtils.closeResultSet(rs); DBUtils.closeStatement(statement); DBUtils.closeConnection(connection);
是写的一个通用方法DBUtils,管理连接,结果集和statement。
但我不知道这种调用方式会不会有其他的问题,所以请大家帮我参考下。
===========================
另外我在Jdon发帖子的时候,老是要重新登陆,我不得不复制写下东西。可能一个原因是SESSION设置的失效时间太短,希望管理员解决下。

0。我最关心的这个代码会不会出现连接无限增长,无法关闭的问题。
rs.last()在数据量很大的时候会不会出现性能问题。
这样的事务调用方式,累似hibernate的调用方式,虽然生效,但不知道会不会有其他问题和弊病。

1.为什么不用现成的开源产品如hibernate,ibats?
回答:并不是每个项目都适合用hibernate,不是说hibernate的能力适用不适用,而是开发人员的学习能力。毕竟hibernate中还是有很多东西需要学习,如果有些问题注意不好会出现性能问题,比如我前段时间碰见过延迟加载没有设置,导致列表页面超级慢。比如关联删除没有设置好,也会出问题。还有出了问题,人的第一个放应是框架的问题,不是自己问题。

而我写的JDBC只是简单的封装,学习门槛低,对付一些小的项目是很合适的。hibernate虽然开源,但真正能大体看懂源码得人很少。

2。这个代码不适合预处理查询和大字段(BLOB)的查询
是,这个需要在之后加入。
预处理查询 可以参考 Jdon彭老师 的jdbcUtil.setQueryParams(queryParams, ps);
blob 我只想写一个插入函数,和查询findbykey()的方法,不会在一般列表查询中也把blob,查询出来。

3.rs.getString都用这个函数似乎有偷工减料的嫌疑。
rs.getString 对一般的类型都可以取出,可能效率不是最好,但是问题应该不大。取出后在进行类型的转换。
Jdon的彭老师用的 rs.getObject
这个也是我有疑问的地方。
4。这个代码不支持分页查询
是,这个也需要在之后加入。
5。查询的结果没有返回,只是打印。
是,我回将结果放入的一个rowSet 种,rowSet中放入row.
6.不够优化,没有对各种数据库进行优化。
是,我看了hibernate的Dialect,可以搬过来。

最后我觉得这个东西还是有用的,适合比较简单,业务不复杂但要求进度的项目。

你的这些方法的确会碰到一些麻烦。
1)使用者对其概念不完整的模糊认识导致的问题。
你的例子中,只需要开启事务和提交事务。一般来说都会对是否关闭了连接有疑问。且在你的提交事务之前,开启事务之候,如果发生异常,你的连接就没有关闭,你无法使用try{}catch{}finally{}.
2)executeQuery()有性能问题。
你在log.debug()中访问了ResultSet的元数据,一般来说元数据总是比较慢的。如果你想通过设置log的级别来消除影响,你需要将这些log写为
if(log.isDebugEnabled()){log.debug(...)}
你的isgetTotalNum参数看来也是用作debug用的,用法应改为上述方式。

不错,首先你勇于探索精神值得肯定,试图通过重用来提高程序的开发效率和健壮性,很不错。

你的其实是JDBC模板,可以解决一些简单程序问题,只要传入SQL语句就可以。

查询语句好像if else判断太多,容易有陷阱bug存在,如果真是这样,不如直接使用JDBC更加针对具体问题。

使用模板的一个通用问题时,因为不能针对具体问题提出专用性能解决方案,所以总体性能平均水平都是打折扣的,就象rs.last()这样,因此必须配合缓存来弥补这个缺陷,在JF中是这样做的。