編程生活

             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            113 隨筆 :: 0 文章 :: 18 評論 :: 0 Trackbacks
          openJPA的用戶說明文檔中說明,在用createNativeQuery時,如果不是SELEC,則統一按存儲過程調用處理,但Oracle的存儲過程返回結果集的情況與MSSQL和Sybase等數據庫均不相同,它是返回一個引用游標,而不是直接返回結果集,即對CallableStatement不能直接調用executeQuery來取得結果集,而必須先用excute,然后用statement.getObject(int index)來取得結果集,因此,必須對源程序進行修改(0.9.7-1.0.0均要改)。按openJPA的設計思想,我在DBDictionary.java中(openjpa-jdbc組件下)增加兩個方法

          public class DBDictionary
              
          implements Configurable, ConnectionDecorator, JoinSyntaxes,
              LoggingConnectionDecorator.SQLWarningHandler 


          /**
               * register stored procedure resultset parameters
               * 
          @param stmnt
               * 
          @throws SQLException
               
          */

              
          public void regStoredProcedureResultParam(CallableStatement stmnt) throws SQLException {
              }

              
              
          /**
               * get stored procedure resultset
               * 
          @param stmt
               * 
          @return 
               * 
          @throws SQLException
               
          */

              
          public ResultSet getStoredProcedureOutResult(CallableStatement stmnt) throws SQLException {
                
          return null;
              }
           
          }
          然后修改OracleDictionary.java(openjpa-jdbc組件下),具體實現這兩個方法
          public class OracleDictionary
              
          extends DBDictionary {

              
          /**
               * register stored procedure resultset parameters
               * 
          @param stmnt
               * 
          @throws SQLException
               
          */

              
          public void regStoredProcedureResultParam(CallableStatement stmnt) throws SQLException {
                stmnt.registerOutParameter(
          1-10);
              }

              
              
          /**
               * get stored procedure resultset
               * 
          @param stmt
               * 
          @return 
               * 
          @throws SQLException
               
          */

              
          public ResultSet getStoredProcedureOutResult(CallableStatement stmnt) throws SQLException {
                stmnt.execute();
                
          return (ResultSet) stmnt.getObject(1);
              }
              
          }

          對于其它的數據庫,請打開對應的Dictionary.java,進行針對性修改(我只用Oracle)
          然后再修改SQLStoreQuery.java
          public class SQLStoreQuery extends AbstractStoreQuery {
          private static class SQLExecutor extends AbstractExecutor {

          public ResultObjectProvider executeQuery(StoreQuery q, Object[] params, Range range) {
                JDBCStore store 
          = ((SQLStoreQuery) q).getStore();
                DBDictionary dict 
          = store.getDBDictionary();
                String sql 
          = q.getContext().getQueryString();

                List paramList;
                
          if (params.length > 0{
                  paramList 
          = new ArrayList(Arrays.asList(params));
                  
          try {
                    sql 
          = substituteParams(sql, paramList);
                  }
           catch (IOException ioe) {
                    
          throw new UserException(ioe);
                  }

                }
           else
                  paramList 
          = Collections.EMPTY_LIST;

                SQLBuffer buf 
          = new SQLBuffer(dict).append(sql);
                Connection conn 
          = store.getConnection();
                JDBCFetchConfiguration fetch 
          = (JDBCFetchConfiguration) q.getContext().getFetchConfiguration();

                
          boolean wrcall = false;
                ResultObjectProvider rop;
                PreparedStatement stmnt 
          = null;
                
          try {
                  
          // use the right method depending on sel vs. proc, lrs setting
                  if (_select && !range.lrs)
                    stmnt 
          = buf.prepareStatement(conn);
                  
          else if (_select)
                    stmnt 
          = buf.prepareStatement(conn, fetch, -1-1);
                  
          else {
                    
          // stored procedure
                    if (!range.lrs)
                      stmnt 
          = buf.prepareCall(conn);
                    
          else
                      stmnt 
          = buf.prepareCall(conn, fetch, -1-1);
                    
          // if the stored procedure has resultset,set the out resultset param
                    if (q.getContext().getResultType() != null{
                      dict.regStoredProcedureResultParam((CallableStatement) stmnt);
                      wrcall 
          = true;
                    }

                  }

                  
          int index = 0;
                  
          for (Iterator i = paramList.iterator(); i.hasNext();)
                    dict.setUnknown(stmnt, 
          ++index, i.next(), null);

                  ResultSetResult res 
          = new ResultSetResult(conn, stmnt, wrcall ? dict
                      .getStoredProcedureOutResult((CallableStatement) stmnt) : stmnt.executeQuery(), store);
                  
          if (_resultMapping != null)
                    rop 
          = new MappedQueryResultObjectProvider(_resultMapping, store, fetch, res);
                  
          else if (q.getContext().getCandidateType() != null)
                    rop 
          = new GenericResultObjectProvider((ClassMapping) _meta, store, fetch, res);
                  
          else
                    rop 
          = new SQLProjectionResultObjectProvider(store, fetch, res, q.getContext().getResultType());
                }
           catch (SQLException se) {
                  
          if (stmnt != null)
                    
          try {
                      stmnt.close();
                    }
           catch (SQLException se2) {
                    }

                  
          try {
                    conn.close();
                  }
           catch (SQLException se2) {
                  }

                  
          throw SQLExceptions.getStore(se, dict);
                }


                
          if (range.start != 0 || range.end != Long.MAX_VALUE)
                  rop 
          = new RangeResultObjectProvider(rop, range.start, range.end);
                
          return rop;
              }

          用maven重新編譯和打包,即可。
          用法:
          EntityManager em = ...
          Query q = em.createNativeQuery("{?=call a()}", A.class);
          List<?> list q.getResultList();
          posted on 2007-10-30 09:14 wilesun 閱讀(1528) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 开封县| 雅安市| 巴林左旗| 宜兰市| 军事| 秭归县| 永济市| 泊头市| 报价| 大连市| 洪湖市| 都安| 抚顺市| 浑源县| 龙口市| 达州市| 北票市| 新绛县| 元江| 安新县| 大化| 泾源县| 塔城市| 丹棱县| 资溪县| 务川| 丰城市| 教育| 虞城县| 安泽县| 阳朔县| 闸北区| 崇文区| 保德县| 上蔡县| 凤山市| 临泉县| 雅安市| 榕江县| 兰州市| 佛教|