项目中的一个问题--返回游标结果集
来源:互联网 发布:php mysql 连接池 编辑:程序博客网 时间:2024/05/21 19:38
几句题外话:
现在越来越觉得数据库的重要作用,程序只是实现这样或那样的业务过程,没有数据库的支撑,程序再怎么写都是鸡肋,特别是大型互联网的应用,数据库绝对是一个重要的方面。
需求背景描述:
在真实的项目中,有这样一个需求:现在有三张数据库表,一张商品信息表productInfo,一张商品定价表productPricing,一张商品整体定价表prodoctUnityPricing。这三张表的表结构如下(注:为了叙述的方便,在此省略了很多字段):
表一:商品信息表productInfo
该表存储的是商品的相关信息。
表二:商品定价表productPricing
该表存储的是商品的定价信息,即将商品信息表productInfo的商品重新修订价格之后,会将修改的价格信息存储在该表中。
表三:商品整体定价表prodoctUnityPricing
该表存储的是某类商品的整体定价,例如将商品类型productType=10001的商品整体调整价格,使价格统一上浮100元,这种整体价格调整信息将存储在该表中。
业务需求描述:
要处理的问题是从这三张表中获取商品信息,显然,如果只是仅仅查询出商品信息,从商品信息表productInfo查询就够了,但不同的用户他所看到的商品的价格是不一样的。
因此,就出现了下面的几种情况:
1.当商品没有定价(即商品定价表productPricing没有该用户对应的定价记录),并且也没有商品整体定价(即商品整体定价表prodoctUnityPricing没有该用户对应的定价记录),则直接查询商品信息表productInfo中的数据;
2.当商品有定价,但商品没有整体定价,则查询商品信息表productInfo表的数据,但价格是商品定价表productPricing对应的价格,其中当部分商品有定价,部分商品没有定价,则有定价的显示定价价格,无定价的显示商品信息表中的价格;
3当商品有整体定价,但商品没有商品定价,则要将商品信息表的价格都加上整体定价上浮的钱数之后才是最终显示给用户的价格;
4.当商品有定价,并且商品也有整体定价,则优先显示定价的价格。
业务过程如上,该功能也已经上线很久了,但线上的版本使用的是sql查询,sql语句也比较复杂,最近做了一个使用存储过程的版本。
给大家参考的同时也盼望大家看看有没有什么问题呢?
下面是存储过程代码,使用package和package bodies结构:
- create or replace package package_productprice is
- -- Author : hnylj
- type resultList is ref cursor;
- procedure processProductPrice(p_userid in varchar2,
- p_productType in varchar2,
- p_pageIndex in number,
- p_pageEnd in number,
- productList out resultList);
- end package_productprice;
create or replace package package_productprice is -- Author : hnylj type resultList is ref cursor; procedure processProductPrice(p_userid in varchar2, p_productType in varchar2, p_pageIndex in number, p_pageEnd in number, productList out resultList);end package_productprice;
- create or replace package body package_productprice is
- procedure processProductPrice(p_userid in varchar2,
- p_productType in varchar2,
- p_pageIndex in number,
- p_pageEnd in number,
- productList out resultList) is
- --商品整体定价(上浮的钱数)
- v_productUnityPrice number(8, 2) := 0.00;
- --判断是否有整体定价
- v_count number(1) := 0;
- begin
- --查询是否有商品的整体定价
- select count(*)
- into v_count
- from PRODOCTUNITYPRICING a
- where a.userid = p_userid
- and a.producttype = p_productType;
- --如果不存在整体定价
- if v_count = 0 then
- --查询商品表和商品定价表
- open productList for
- SELECT *
- FROM (SELECT AA.*, ROWNUM RN
- FROM (select t.*, p.productPricing
- from (select a.productid productId,
- a.productname productName,
- decode(a.productprice,
- null,
- 0.00,
- a.productprice) productPrice,
- a.producttype productType
- from productinfo a
- where a.producttype = p_productType) t,
- (select b.productid productId,
- decode(b.PRODUCPRICING,
- null,
- 0.00,
- b.PRODUCPRICING) productPricing
- from productpricing b
- where b.producttype = p_productType
- and b.userid = p_userid) p
- where t.productId = p.productId(+)
- order by t.productPrice) AA
- WHERE ROWNUM <= p_pageEnd)
- WHERE RN >= p_pageIndex;
- end if;
- --如果存在整体定价
- if v_count > 0 then
- --查询出整体定价上浮的钱数存入v_productUnityPrice变量
- select decode(a.unitypricing, null, 0, a.unitypricing)
- into v_productUnityPrice
- from PRODOCTUNITYPRICING a
- where a.userid = p_userid
- and a.producttype = p_productType;
- --查询商品表和商品定价表
- open productList for
- SELECT *
- FROM (SELECT AA.*, ROWNUM RN
- FROM (select t.*, decode(p.productPricing, null, t.productPrice+v_productUnityPrice, p.productPricing) productPricing
- from (select a.productid productId,
- a.productname productName,
- decode(a.productprice,
- null,
- 0.00,
- a.productprice) productPrice,
- a.producttype productType
- from productinfo a
- where a.producttype = p_productType) t,
- (select b.productid productId,
- decode(b.PRODUCPRICING,
- null,
- 0.00,
- b.PRODUCPRICING) productPricing
- from productpricing b
- where b.producttype = p_productType
- and b.userid = p_userid) p
- where t.productId = p.productId(+)
- order by t.productPrice) AA
- WHERE ROWNUM <= p_pageEnd)
- WHERE RN >= p_pageIndex;
- --循环游标开始
- end if;
- end processProductPrice;
- end package_productprice;
create or replace package body package_productprice is procedure processProductPrice(p_userid in varchar2, p_productType in varchar2, p_pageIndex in number, p_pageEnd in number, productList out resultList) is --商品整体定价(上浮的钱数) v_productUnityPrice number(8, 2) := 0.00; --判断是否有整体定价 v_count number(1) := 0; begin --查询是否有商品的整体定价 select count(*) into v_count from PRODOCTUNITYPRICING a where a.userid = p_userid and a.producttype = p_productType; --如果不存在整体定价 if v_count = 0 then --查询商品表和商品定价表 open productList for SELECT * FROM (SELECT AA.*, ROWNUM RN FROM (select t.*, p.productPricing from (select a.productid productId, a.productname productName, decode(a.productprice, null, 0.00, a.productprice) productPrice, a.producttype productType from productinfo a where a.producttype = p_productType) t, (select b.productid productId, decode(b.PRODUCPRICING, null, 0.00, b.PRODUCPRICING) productPricing from productpricing b where b.producttype = p_productType and b.userid = p_userid) p where t.productId = p.productId(+) order by t.productPrice) AA WHERE ROWNUM <= p_pageEnd) WHERE RN >= p_pageIndex; end if; --如果存在整体定价 if v_count > 0 then --查询出整体定价上浮的钱数存入v_productUnityPrice变量 select decode(a.unitypricing, null, 0, a.unitypricing) into v_productUnityPrice from PRODOCTUNITYPRICING a where a.userid = p_userid and a.producttype = p_productType; --查询商品表和商品定价表 open productList for SELECT * FROM (SELECT AA.*, ROWNUM RN FROM (select t.*, decode(p.productPricing, null, t.productPrice+v_productUnityPrice, p.productPricing) productPricing from (select a.productid productId, a.productname productName, decode(a.productprice, null, 0.00, a.productprice) productPrice, a.producttype productType from productinfo a where a.producttype = p_productType) t, (select b.productid productId, decode(b.PRODUCPRICING, null, 0.00, b.PRODUCPRICING) productPricing from productpricing b where b.producttype = p_productType and b.userid = p_userid) p where t.productId = p.productId(+) order by t.productPrice) AA WHERE ROWNUM <= p_pageEnd) WHERE RN >= p_pageIndex; --循环游标开始 end if; end processProductPrice;end package_productprice;
存储过程代码如上,使用的动态游标ref cursor。
下面是一段java调用该存储过程的测试代码:
- package com.javaeye.hnylj.test;
- import java.sql.CallableStatement;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
- import com.javaeye.hnylj.model.ProductInfo;
- /**
- * 测试存储过程
- *
- * @since Jun 20, 2010
- */
- public class ProceduresTest {
- private Connection conn = null;
- private CallableStatement cstmt = null;
- private ResultSet rs = null;
- private static final String DRIVER = "oracle.jdbc.driver.OracleDriver";
- private static final String URL = "jdbc:oracle:thin:@127.0.0.1:1521:workdb";
- private static final String USERNAME = "framework";
- private static final String PASSWORD = "framework";
- private List<ProductInfo> list;
- /**
- * 数据库连接
- *
- * @return Connection
- */
- public synchronized Connection getConnection() {
- try {
- Class.forName(DRIVER);
- conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- return null;
- } catch (SQLException e) {
- e.printStackTrace();
- return null;
- }
- return conn;
- }
- /**
- * 调用存储过程得到游标数据集
- *
- * @return
- */
- public List<ProductInfo> queryList() {
- list = new ArrayList<ProductInfo>();
- try {
- if (this.getConnection() != null) {
- conn = this.getConnection();
- cstmt = conn.prepareCall("{call package_productprice.processProductPrice(?,?,?,?,?)}");
- cstmt.setString(1, "0001");
- cstmt.setString(2, "10001");
- cstmt.setInt(3, 1);
- cstmt.setInt(4, 10);
- cstmt.registerOutParameter(5, oracle.jdbc.OracleTypes.CURSOR);
- cstmt.execute();
- rs = (ResultSet)cstmt.getObject(5);
- while (rs.next()) {
- ProductInfo productInfo = new ProductInfo();
- productInfo.setProductId(rs.getString(1));
- productInfo.setProductName(rs.getString(2));
- productInfo.setProductPrice(rs.getDouble(3));
- productInfo.setProductType(rs.getString(4));
- productInfo.setProductPricing(rs.getDouble(5));
- list.add(productInfo);
- }
- }
- } catch (SQLException e) {
- e.printStackTrace();
- } finally {
- try {
- if (null != rs) {
- rs.close();
- }
- if (null != cstmt) {
- cstmt.close();
- }
- if (null != conn) {
- conn.close();
- }
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- return list;
- }
- /**
- * main方法测试
- *
- * @param args
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- ProceduresTest test = new ProceduresTest();
- List<ProductInfo> productList = test.queryList();
- for (ProductInfo productInfo : productList) {
- System.out.println(productInfo.getProductId());
- System.out.println(productInfo.getProductName());
- System.out.println(productInfo.getProductPrice());
- System.out.println(productInfo.getProductPricing());
- System.out.println(productInfo.getProductType());
- }
- }
- }
package com.javaeye.hnylj.test;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import com.javaeye.hnylj.model.ProductInfo;/** * 测试存储过程 * * @since Jun 20, 2010 */public class ProceduresTest {private Connection conn = null;private CallableStatement cstmt = null;private ResultSet rs = null;private static final String DRIVER = "oracle.jdbc.driver.OracleDriver";private static final String URL = "jdbc:oracle:thin:@127.0.0.1:1521:workdb";private static final String USERNAME = "framework";private static final String PASSWORD = "framework";private List<ProductInfo> list;/** * 数据库连接 * * @return Connection */public synchronized Connection getConnection() {try {Class.forName(DRIVER);conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);} catch (ClassNotFoundException e) {e.printStackTrace();return null;} catch (SQLException e) {e.printStackTrace();return null;}return conn;}/** * 调用存储过程得到游标数据集 * * @return */public List<ProductInfo> queryList() {list = new ArrayList<ProductInfo>();try {if (this.getConnection() != null) {conn = this.getConnection();cstmt = conn.prepareCall("{call package_productprice.processProductPrice(?,?,?,?,?)}");cstmt.setString(1, "0001");cstmt.setString(2, "10001");cstmt.setInt(3, 1);cstmt.setInt(4, 10);cstmt.registerOutParameter(5, oracle.jdbc.OracleTypes.CURSOR);cstmt.execute();rs = (ResultSet)cstmt.getObject(5);while (rs.next()) {ProductInfo productInfo = new ProductInfo();productInfo.setProductId(rs.getString(1));productInfo.setProductName(rs.getString(2));productInfo.setProductPrice(rs.getDouble(3));productInfo.setProductType(rs.getString(4));productInfo.setProductPricing(rs.getDouble(5));list.add(productInfo);}}} catch (SQLException e) {e.printStackTrace();} finally {try {if (null != rs) {rs.close();}if (null != cstmt) {cstmt.close();}if (null != conn) {conn.close();}} catch (SQLException e) {e.printStackTrace();}}return list;}/** * main方法测试 * * @param args * @throws Exception */public static void main(String[] args) throws Exception {ProceduresTest test = new ProceduresTest();List<ProductInfo> productList = test.queryList();for (ProductInfo productInfo : productList) {System.out.println(productInfo.getProductId());System.out.println(productInfo.getProductName());System.out.println(productInfo.getProductPrice());System.out.println(productInfo.getProductPricing());System.out.println(productInfo.getProductType());}}}
另外还需要一个model类ProductInfo,该类的代码只要productId、productName、productPrice、productPricing、productType及相应的getter和setter方法。
- 项目中的一个问题--返回游标结果集
- PL/SQL 测试游标返回结果集
- oracle 游标 返回查询结果集
- oracle 游标 返回结果集 例子
- 一个存储过程 游标循环结果集
- 一个SSL 请求结果返回问题
- 问题Jpa 返回别名,一个结果集取值
- Oracle利用游标返回结果集的的例子(C#)
- 执行Oracle存储过程返回游标结果集
- java调用oracle过程返回结果集(包和游标)
- 通过游标读取oracle存储过程返回的结果集
- 存储过程使用游标变量返回结果集
- 如何接收游标变量返回的结果集
- 存储过程使用游标变量返回结果集(推荐)
- oracle SYS_REFCURSOR返回结果集及动态游标使用方法
- SSM-Mybatis调用Oracle存储过程返回结果集(游标)
- mybaits中的返回结果resultType的问题
- 结果集游标
- java hasNext方法误解
- Oracle11g使用exp导出空表
- 动态语言之“动”
- custom format Property of business object for the data binding
- pci总线一些基础问题
- 项目中的一个问题--返回游标结果集
- java多线程 生产者 消费者 问题 。。。
- ORA-01653错误解决办法
- DataTable里添加一个标识列
- 又起波折
- Oracle bug 之ORA-00600 [LibraryCacheNotEmptyOnClose]
- Asp.net网页画图
- zend studio 的zend debug代码跟踪和添加todo list
- Tab Layout Tutorials 详解