在处理计算结果集的应用时,如果仅仅从数据库中获取相应的数据,把业务实现过程放到java代码来实现,对于数据量小的情况也许可以完全应付,只是对于大数据量的业务计算逻辑时,会造成与数据库的频繁交互,消耗不必要的内存资源。针对这些问题,有时候使用缓存能在一定程度上减少对数据库的访问,从而提高程序的应用性能。不过,更好的解决办法应该是在数据层完成这些业务计算,而程序访问数据库时就可以直接将计算结果集获取到,从而大大提高了程序应用性能,减少了很多不必要的内存消耗。
在项目开发中,我也遇到过类似的问题,后来通过plsql编程,使用嵌套表很顺利地解决了这个问题。下面就简单以oracle的示例来展示嵌套表的应用。
1. 创建object类型:
create or replace type company_info_record as object(empname varchar2(100), job varchar2(100), sal number(10,2), dname varchar2(100) ); 2. 创建表类型:
create or replace type company_info_table is table of company_info_record;
3. 创建一个包进行封装,包中创建一个procedure,并通过一个游标返回计算结果集。3.1)包声明:
type cur_back_company_info is ref cursor; procedure proc_check_company_info(p_tax_rate in number, p_cur_back_info out cur_back_company_info); 3.2) 包体:
procedure proc_check_company_info(p_tax_rate in number, ----税率,要求每个员工的薪水都是税后的 p_cur_back_info out cur_back_company_info) is cursor cur_get_nested_msg is select d.dname dname, e.ename ename, e.sal sal, e.job job from emp e left join dept d on e.deptno = d.deptno; v_cur_nested_info cur_get_nested_msg%rowtype; v_company_info company_info_table := company_info_table(); v_count number(5); begin v_count := 1; open cur_get_nested_msg; loop fetch cur_get_nested_msg into v_cur_nested_info; exit when cur_get_nested_msg%notfound; if v_cur_nested_info.sal > 0 and p_tax_rate > 0 then v_cur_nested_info.sal := round(v_cur_nested_info.sal * p_tax_rate, 2); end if; v_company_info.extend; v_company_info(v_count) := company_info_record(v_cur_nested_info.ename, v_cur_nested_info.dname, v_cur_nested_info.sal, v_cur_nested_info.job); v_count := v_count + 1; end loop; close cur_get_nested_msg; open p_cur_back_info for select * from table(cast(v_company_info as company_info_table)); exception when others then raise; end proc_check_company_info;
4.java调用,(如果使用ibatis或hibernate则需要配置)
5.main方法调用输出:package com.databaseConnection; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import oracle.jdbc.OracleTypes; /** * * @author * @date: 2011-3-31上午12:05:14 */ public class Connector { private String url = "jdbc:oracle:thin:@192.168.133.125:1521:orcl"; private String userName = "scott"; private String pwd = "tan123"; private Connection conn = null; public Connection connect() { try { Class.forName("oracle.jdbc.driver.OracleDriver"); try { this.conn = DriverManager.getConnection(this.url, this.userName, this.pwd); String sql="{call scott_test_pkg.proc_check_company_info(?,?)}";//"{call scott_test_pkg.proc_sp_pro9(?,?)}"; CallableStatement callStatement=conn.prepareCall(sql); //callStatement.setInt(1, 10); callStatement.setFloat(1, Float.parseFloat("0.96")); callStatement.registerOutParameter(2, OracleTypes.CURSOR); callStatement.execute(); ResultSet set=(ResultSet)callStatement.getObject(2); while(set.next()){ //System.out.println(set.getInt(1)+" "+set.getString(2)+" "+set.getString(3)+" "); System.out.println(set.getString(1)+" "+set.getString(2)+" "+set.getDouble(3)+" "+set.getString(4)); } callStatement.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } catch (Exception exception) { exception.printStackTrace(); } return this.conn; } }
6.输出结果:package com.databaseConnection; public class DbConnectionApp { public static void main( String[] args ) { Connector connector=new Connector(); connector.connect(); } }
MILLER ACCOUNTING 1248.0 CLERK KING ACCOUNTING 4800.0 PRESIDENT CLARK ACCOUNTING 2352.0 MANAGER FORD RESEARCH 2880.0 ANALYST ADAMS RESEARCH 1056.0 CLERK SCOTT RESEARCH 2880.0 ANALYST JONES RESEARCH 2856.0 MANAGER SMITH RESEARCH 768.0 CLERK JAMES SALES 912.0 CLERK TURNER SALES 1440.0 SALESMAN BLAKE SALES 2736.0 MANAGER MARTIN SALES 1200.0 SALESMAN WARD SALES 1200.0 SALESMAN ALLEN SALES 1536.0 SALESMAN
总结:在实际的项目开发中,plsql编程其实是可以让我们减少很多业务上处理上的烦恼,其中像嵌套表、record等可以很方便地解决我们业务上的困难,尤其是在大数据量的计算时,如果使用java来处理这些工作,将会很繁琐且性能低下的选择。
以上仅是简单案例,如有不足,请提出,愿与大家共同学习。