在JAVA中实现数据库存储过程的统一调用

来源:互联网 发布:2014电影票房数据库 编辑:程序博客网 时间:2024/06/13 05:43

在业务处理过程中,总是要不停的访问数据库,如果仅仅利用SQL语句来实现数据的读取或更新插入,有时候往往导致业务处理层和数据层的逻辑结构过于复杂,接口太多难于管理.幸运的是,数据库的存储过程为我们保持接口的简洁和逻辑的清晰提供了很好的实现方式.通过存储过程,可以把复杂的操作都封装起来,提供的接口来实现复杂的功能.

但随着业务逻辑的进一步复杂,可能存储过程也很快膨胀起来,如果每调用一次存储过程都要重复建立数据库连接、传递参数、处理返回结果、释放连接等操作 ,无疑也会大大增加重复内容,不易对接口进行统一的管理。但如果统一起来,创建连接很好处理都一样的,但因传递的参数不同、返回结果不同,处理起来就比较麻烦了。

经过研究发现,可以把创建数据库连接、传递参数(用可变Object数组,具体类型在内部转换)、释放连接这几步抽象出来,把处理返回结果再根据不同的接口具体处理。

首先定义一个调用返回结果类,包括数据连接、一个结果集、一个字符串结果(常用的整型、字符串、日期型都可以自动转化成字符串型,在具体处理返回结果时可以再次进行转换,这样保证返回结果的简洁,只有两种类型便于处理):

package com.gftech.dp.bean;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.log4j.Logger;

import com.gftech.util.GFConn;
import com.gftech.util.GFString;

public class PLSQLResult {
    
private String srs;// 调用PLSQL后返回的整形结果

    
private ResultSet rs;// 返回的结果集

    
private GFConn gfconn;// 数据库连接

    
static Logger logger = Logger.getLogger(PLSQLResult.class);

    
public GFConn getGfconn() {
        
return gfconn;
    }


    
public void setGfconn(GFConn gfconn) {
        
this.gfconn = gfconn;
    }

 

    
public String getSrs() {
        
return srs;
    }


    
public void setSrs(String srs) {
        
this.srs = srs;
    }


    
public ResultSet getRs() {
        
return rs;
    }


    
public void setRs(ResultSet rs) {
        
this.rs = rs;
    }


    
public void close() {
        
if (rs != null)
            
try {
                rs.close();
            }
 catch (SQLException e) {
                logger.error(e);
            }

        
if (gfconn != null)
            gfconn.close();

    }

    
    
public int srs2int(){
        
if(srs!=null && GFString.isNumeric(srs)){
            
return GFString.cint(srs);
        }

        
        
return 0;
    }

    
    
public boolean srs2bool(){
        
if("1".equals(srs))
            
return true;
        
return false;
    }

}

 

抽象出创立连接、传递参数等共性的东西

 

/**
     * 调用PLSQL存储过程,返回调用结果,处理完毕后要记得调用close()关闭结果集和连接
     * 
@param gfdb 数据库
     * 
@param plsqlName 存储过程名称
     * 
@param oracleType 数据库类型,特指调用返回结果的类型
     * 
@param isIntegerNull 整形参数为0时是否按NULL指针传递
     * 
@param params 存储过程的参数列表
     * 
@return
     
*/

    
public static PLSQLResult callPLSQL(GFDB gfdb, String plsqlName, int oracleType, boolean isIntegerNull,
            Object... params) 
{
        PLSQLResult prs 
= null;
        ResultSet rs 
= null;
        String allName 
= null;
        GFConn gfconn 
= null;
        Connection conn 
= null;
        String srs 
= null;
        String cName 
= null;

        
long start = System.currentTimeMillis();
        PropertyConfigurator.configure(ConfParam.LOG4J_PROP_CONF);
        
if (gfdb != null && plsqlName != null && params != null{
            allName 
= "{?=call " + plsqlName + "(";
            
for (int i = 0; i < params.length; i++{
                
if (i == params.length - 1)
                    allName 
+= "?";
                
else
                    allName 
+= "?,";

            }

            allName 
+= ")}";

            
if (gfdb == null)
                
return null;

            
for (int i = 0; i < 3; i++{
                gfconn 
= gfdb.getConn();
                
if (gfconn == null{
                    
if (i == 2)
                        MonReport.errorReport(DPMain.conf.err_server_host, DPMain.conf.err_server_port, 
false,
                                
"DH-无法取得数据库连接");
                    
else
                        logger.error(
"DH-无法取得数据库连接");
                    
continue;
                }

                conn 
= gfconn.getConn();
                
if (conn != null{
                    
try {
                        CallableStatement proc 
= conn.prepareCall(allName);
                        proc.registerOutParameter(
1, oracleType);

                        
for (int j = 0; j < params.length; j++{
                            cName 
= GFCommon.getClassName(params[j]);

                            
if ("String".equals(cName)) {
                                proc.setString(j 
+ 2, (String) params[j]);
                                logger.debug(
"plsql_param_string:" + params[j]);
                            }
 else if ("Integer".equals(cName)) {
                                
if (isIntegerNull && ((Integer) params[j]).intValue() <= 0{
                                    proc.setNull(j 
+ 2, Types.INTEGER);
                                    logger.debug(
"plsql_param_int:null");
                                }
 else {
                                    proc.setInt(j 
+ 2, ((Integer) params[j]).intValue());
                                    logger.debug(
"plsql_param_int:" + params[j]);
                                }


                            }
 else if ("Long".equals(cName)) {
                                proc.setLong(j 
+ 2, ((Long) params[j]).longValue());
                                logger.debug(
"plsql_param_long:" + params[j]);
                            }
 else if ("Double".equals(cName)) {
                                proc.setDouble(j 
+ 2, ((Double) params[j]).doubleValue());
                                logger.debug(
"plsql_param_double:" + params[j]);
                            }
 else if ("Float".equals(cName)) {
                                proc.setFloat(j 
+ 2, ((Float) params[j]).floatValue());
                                logger.debug(
"plsql_param_float:" + params[j]);
                            }
 else if (cName != null && cName.indexOf("Calendar"!= -1{
                                proc.setTimestamp(j 
+ 2, GFDate.cal2timestamp((Calendar) params[j]));
                                logger.debug(
"plsql_param_date:"
                                        
+ GFDate.cdate((Calendar) params[j], "yyyy-mm-dd hh24:mi:ss"));
                            }
 else {
                                proc.setString(j 
+ 2null);
                                logger.debug(
"plsql_param_null:" + params[j]);

                            }


                        }

                        proc.executeUpdate();
                        
switch (oracleType) {
                        
case OracleTypes.CURSOR:
                            rs 
= (ResultSet) proc.getObject(1);
                            
break;
                        
case OracleTypes.INTEGER:
                        
case OracleTypes.VARCHAR:
                        
case OracleTypes.DATE:
                            srs 
= proc.getString(1);
                            
break;

                        }

                        prs 
= new PLSQLResult();
                        prs.setGfconn(gfconn);
                        prs.setSrs(srs);
                        prs.setRs(rs);
                        proc.close();

                    }
 catch (SQLException e) {
                        gfconn.close();
                        String err 
= "调用存储过程" + plsqlName + "时出错";
                        logger.error(err, e);
                        gfdb.catchException(e);
                        
continue;
                    }

                }
 else {
                    logger.error(
"can't get connection");
                    MonReport.errorReport(DPMain.conf.err_server_host, DPMain.conf.err_server_port, 
true"无法取得数据库连接");
                }


                
break;
            }

        }


        DPMain.stat.addDbTime(System.currentTimeMillis() 
- start);
        DPMain.stat.addDbCount();
        
return prs;
    }

这样一来,我们在调用PLSQL时,就简单多了,测试用例如下:

 

/**
     * 判断是否是虚拟ID号
     * 
     * 
@param id
     * 
@return
     
*/

    
private boolean isVirtualID(String id) {
        
boolean result = false;
        String plsqlName 
= "pkg_deal_comm.f_is_virtual";

        GFDB gfdb 
= DPMain.getDB(3);
        
if(gfdb!=null)
            PLSQLResult pr 
= DPCommon.callPLSQL(gfdb, plsqlName, OracleTypes.INTEGER, false,id);
            
if (pr != null{
                result
=pr.srs2bool();
                pr.close();
            }

        }

         

        
return result ;
    }


private void readSendList() {
        
final String plsqlName = "pkg_tenancy_comm.f_read_buffer";
        
// final String plsqlName = "pkg_tenancy_comm.f_temp";
        ResultSet rs = null;
        SmpSubmitPack sp 
= null;
        GFDB gfdb 
= DPMain.getDB(1);
        
if (gfdb != null{
            PLSQLResult pr 
= DPCommon.callPLSQL(gfdb, plsqlName, OracleTypes.CURSOR, false);
            
if (pr != null{
                rs 
= pr.getRs();
                
if (rs == null)
                    
return;
                
try {
                    
while (rs.next()) {
                        
boolean isFree = false;
                        
int biztype = BizType.GENERAL;
                        sp 
= new SmpSubmitPack();
                        sp.setSrcAddr(rs.getString(
1));
                        sp.addDestAddr(rs.getString(
2));
                        sp.setContent(rs.getString(
3));
                        FeeInfo fee 
= new FeeInfo();
                        fee.setFeeType((
byte) GFString.cint(rs.getString(5)));
                        
if (fee.getFeeType() != FeeType.FREE) {
                            biztype 
= BizType.VIRTUAL_TALK;
                            sp.setBizCode(rs.getString(
4));
                            fee.setFeeValue(rs.getInt(
6));
                            isFree 
= true;
                        }

                        sp.setFeeInfo(fee);
                        sp.setLinkID(rs.getString(
7));
                        sp.setMsgStamp(rs.getString(
8));
                        DPCommon.putSendBuffer(biztype, 
1, sp, isFree);

                    }

                }
 catch (SQLException e) {
                    logger.error(e);
                }


                pr.close();
            }

        }


    }

这样一来,大大降低了重复性的工作,并且有利代码的一致性,便于代码的维护。

说明:上述所示只是为主要的代码示例,可能包含其它需要依赖的类库才能直接运行。

 

原创粉丝点击