Share a Java paging code for different databases

From , 3 Years ago, written in Java, viewed 224 times.
URL https://pastebin.vip/view/e3b21256
  1. package org.rwl.utils.db;
  2.  
  3. import org.apache.log4j.Logger;
  4. import org.rwl.utils.db.dialect.ExtendDialect;
  5. import org.rwl.utils.db.dialect.impl.ExtendDB2Dialect;
  6. import org.rwl.utils.exception.RwlDialectException;
  7.  
  8. /**
  9.  * 数据库SQL规则处理
  10.  * @author polarbear 2009-5-9
  11.  *
  12.  */
  13. public class RwlDBDialectUtil {
  14.        
  15.         private volatile static RwlDBDialectUtil instance = null;
  16.        
  17.         private RwlDBDialectUtil.dbtype currentDialect = RwlDBDialectUtil.dbtype.mysql;
  18.        
  19.         private String SQL_SERVER_VERSION = "2005";
  20.        
  21.         /**
  22.          * 是否支持分页: 1:支持分页(缺省)  0:不支持分页
  23.          */
  24.         private int SQL_SUPPORT_PAGING = 1;
  25.        
  26.         /**
  27.          * 分页处理程序
  28.          */
  29.         public static final ExtendDialect db2Dialect = new ExtendDB2Dialect();
  30.        
  31.         private static Logger log = Logger.getLogger(RwlDBDialectUtil.class);
  32.        
  33.         private RwlDBDialectUtil() {
  34.                 _init();
  35.         }
  36.  
  37.         private void _init() {
  38.                
  39.         }
  40.  
  41.         public static RwlDBDialectUtil getInstance() {
  42.                 if (instance == null) {
  43.                         synchronized (RwlDBDialectUtil.class) {
  44.                                 if (instance == null) {
  45.                                         instance = new RwlDBDialectUtil();
  46.                                 }
  47.                         }
  48.                 }
  49.                 return instance;
  50.         }
  51.        
  52.         /**
  53.          * 获取分页的SQL语句
  54.          * @param _sql 基础语句
  55.          * @param hasOffset 是否限定数量(一般都是true)
  56.          * @param _start 起始数
  57.          * @param _limit 限定的数量
  58.          * @return 返回设定好分页的SQL语句
  59.          * @throws RwlDialectException
  60.          */
  61.         public String getSqlLimit(String _sql, boolean hasOffset, int _start, int _limit) throws RwlDialectException {
  62.                
  63.             if(log.isDebugEnabled()) {
  64.                 log.debug(">>RwlDBDialect-start:" + _sql);
  65.             }
  66.            
  67.                 //add by polarbear , 2009-6-4, 不支持分页的方式
  68.                 if(SQL_SUPPORT_PAGING == 0) {
  69.                         throw new RwlDialectException("Not Support Paging!");
  70.                 }
  71.                
  72.                 /**
  73.                  * #############Oracle/kingbase分页方式###############
  74.                  */
  75.                 if(currentDialect == dbtype.oracle || currentDialect == dbtype.kingbase) {
  76.                         _sql = _sql.trim();
  77.                         boolean isForUpdate = false;
  78.                         if ( _sql.toLowerCase().endsWith(" for update") ) {
  79.                                 _sql = _sql.substring( 0, _sql.length()-11 );
  80.                                 isForUpdate = true;
  81.                         }
  82.                        
  83.                         StringBuffer pagingSelect = new StringBuffer(_sql.length()+100 );
  84.                         if (hasOffset) {
  85.                                 pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
  86.                         }
  87.                         else {
  88.                                 pagingSelect.append("select * from ( ");
  89.                         }
  90.                         pagingSelect.append(_sql);
  91.                         if (hasOffset) {
  92.                                 pagingSelect.append(" ) row_ where rownum <= " + (_start + _limit) + ") where rownum_ > " + _start);
  93.                         }
  94.                         else {
  95.                                 pagingSelect.append(" ) where rownum <= " + (_start + _limit));
  96.                         }
  97.  
  98.                         if (isForUpdate) pagingSelect.append(" for update");
  99.                        
  100.                         //结束
  101.                         if(log.isDebugEnabled()) {
  102.                             log.debug(">>RwlDBDialect-end(oracle):" + pagingSelect.toString());
  103.                         }
  104.                        
  105.                        
  106.                         return pagingSelect.toString();
  107.                 }
  108.                 /**
  109.                  * ############## HSQL方式 ###############
  110.                  */
  111.                 else if(currentDialect == dbtype.hsql) {
  112.                         return new StringBuffer( _sql.length() + 10 )
  113.                         .append( _sql )
  114.                         .insert( _sql.toLowerCase().indexOf( "select" ) + 6, hasOffset ? " limit " + _start + " " + _limit : " top "+_start)
  115.                         .toString();
  116.                 }
  117.                
  118.                 //缺省使用的是mysql的分页方式
  119.                 else if(currentDialect == dbtype.mysql) {
  120.                         String result = new StringBuffer(_sql.length()+20 )
  121.                         .append(_sql)
  122.                         .append( hasOffset ? " limit " + _start + ", " + _limit : " limit " + _start)
  123.                         .toString();
  124.                        
  125.                         //结束
  126.             if(log.isDebugEnabled()) {
  127.                 log.debug(">>RwlDBDialect-end(mysql):" + result);
  128.             }
  129.            
  130.             return result;
  131.                 }
  132.                
  133.                 /**
  134.                  * ############## SQLServer分页方式 ################
  135.                  */
  136.                 else if(currentDialect == dbtype.sqlserver) {
  137.                        
  138.                         if(!SQL_SERVER_VERSION.equals("2005")) {
  139.                                 throw new RwlDialectException("Not Support Paging!");
  140.                         }
  141.                        
  142.                         StringBuffer pagingBuilder = new StringBuffer();  
  143.                         String orderby = getOrderByPart(_sql);  
  144.                         String distinctStr = "";  
  145.  
  146.                         String loweredString = _sql.toLowerCase();  
  147.                         String sqlPartString = _sql.trim();  
  148.                         if (loweredString.trim().startsWith("select")) {  
  149.                                 int index = 6;  
  150.                                 if (loweredString.startsWith("select distinct")) {  
  151.                                         distinctStr = "DISTINCT ";  
  152.                                         index = 15;  
  153.                                 }  
  154.                                 sqlPartString = sqlPartString.substring(index);  
  155.                         }  
  156.                         pagingBuilder.append(sqlPartString);  
  157.  
  158.                         // if no ORDER BY is specified use fake ORDER BY field to avoid errors  
  159.                         if (orderby == null || orderby.length() == 0) {  
  160.                                 orderby = "ORDER BY CURRENT_TIMESTAMP";  
  161.                         }  
  162.  
  163.                         StringBuffer result = new StringBuffer();  
  164.                         result.append("SELECT * FROM (")  
  165.                         .append("SELECT ")  
  166.                         .append(distinctStr)  
  167.                         .append(" TOP 100 PERCENT ROW_NUMBER() OVER (") //使用TOP 100 PERCENT可以提高性能  
  168.                         .append(orderby)  
  169.                         .append(") AS __hibernate_row_nr__, ")  
  170.                         .append(pagingBuilder)  
  171.                         .append(") as ucstarTempTable WHERE __hibernate_row_nr__ >")
  172.                         .append(_start)  
  173.                         .append(" AND __hibernate_row_nr__ <=")  
  174.                         .append(_start + _limit)  
  175.                         .append(" ORDER BY __hibernate_row_nr__");  
  176.                        
  177.                         //结束
  178.             if(log.isDebugEnabled()) {
  179.                 log.debug(">>RwlDBDialect-end(sqlserver):" + result.toString());
  180.             }
  181.                        
  182.                         return result.toString();
  183.                 }
  184.                
  185.                 //IBM的DB2的分页方式
  186.                 else if(currentDialect == dbtype.db2) {
  187.                     String resultSql = db2Dialect.getLimitString(_sql, _start, _limit);
  188.                         //结束
  189.             if(log.isDebugEnabled()) {
  190.                 log.debug(">>RwlDBDialect-end(db2):" + resultSql);
  191.             }
  192.                         return resultSql;
  193.                 }
  194.                
  195.                 /**
  196.                  * ############# 不支持的分页 ##############
  197.                  */
  198.                 else {
  199.                         log.error("No support Paging!");
  200.                         return _sql;
  201.                 }
  202.         }
  203.        
  204.        
  205.         /**
  206.          * SQLServer的处理
  207.          * polarbear 2009-5-9
  208.          * @param sql
  209.          * @return
  210.          */
  211.         static String getOrderByPart(String sql) {
  212.                 String loweredString = sql.toLowerCase();
  213.                 int orderByIndex = loweredString.indexOf("order by");
  214.                 if (orderByIndex != -1) {
  215.                         // if we find a new "order by" then we need to ignore
  216.                         // the previous one since it was probably used for a subquery
  217.                         return sql.substring(orderByIndex);
  218.                 } else {
  219.                         return "";
  220.                 }
  221.         }
  222.        
  223.         private static boolean hasDistinct(String sql) {
  224.                 return sql.toLowerCase().indexOf("select distinct")>=0;
  225.         }
  226.        
  227.         private static String getRowNumber(String sql) {
  228.                 StringBuffer rownumber = new StringBuffer(50)
  229.                         .append("rownumber() over(");
  230.  
  231.                 int orderByIndex = sql.toLowerCase().indexOf("order by");
  232.                
  233.                 if ( orderByIndex>0 && !hasDistinct(sql) ) {
  234.                         rownumber.append( sql.substring(orderByIndex) );
  235.                 }
  236.                          
  237.                 rownumber.append(") as rownumber_,");
  238.                
  239.                 return rownumber.toString();
  240.         }
  241.        
  242.         /**
  243.          * 专门针对DB2处理的SQL代码
  244.          * polarbear 2009-8-31
  245.          * @param _sql
  246.          * @return
  247.          */
  248.         private static String genReturnField(String _sql) {
  249.                 int startOfSelect = _sql.toLowerCase().indexOf("select");
  250.                 int startOfFrom = _sql.toLowerCase().indexOf("from");
  251.                 int startOfWhere = _sql.toLowerCase().indexOf("where");
  252.                 int startOfOrderBy = _sql.toLowerCase().indexOf("order by");
  253.                 int startOfGroupBy = _sql.toLowerCase().indexOf("group by");
  254.                
  255.                 String returnField = "";
  256.                 if(startOfFrom >= 0) {
  257.                         String fromTableStr = "";
  258.                         if(startOfWhere >= 0) {
  259.                                 fromTableStr = _sql.substring(startOfFrom + "from".length(), startOfWhere);
  260.                         } else if(startOfOrderBy >= 0) {
  261.                                 fromTableStr = _sql.substring(startOfFrom + "from".length(), startOfOrderBy);
  262.                         } else if(startOfGroupBy >= 0) {
  263.                                 fromTableStr = _sql.substring(startOfFrom + "from".length(), startOfGroupBy);
  264.                         } else {
  265.                                 fromTableStr = _sql.substring(startOfFrom + "from".length());
  266.                         }
  267.                         if(fromTableStr.length() > 0) {
  268.                                 String[] fromTableStrArr = fromTableStr.split(",");
  269.                                 for(String fromTable : fromTableStrArr) {
  270.                                         if(fromTable != null && fromTable.length() > 0) {
  271.                                                 String fromTable2 = fromTable.trim();
  272.                                                 int startTableName = fromTable2.indexOf(" ");
  273.                                                 String tableNick = "";
  274.                                                 if(startTableName > 0) {
  275.                                                         tableNick = fromTable2.substring(startTableName);
  276.                                                 } else {
  277.                                                         tableNick = fromTable2;
  278.                                                 }
  279.                                                 tableNick = tableNick.trim();
  280.                                                 returnField += tableNick + ".*" + ",";
  281.                                         }
  282.                                        
  283.                                 }
  284.                         }
  285.                         if(returnField.length() > 0) {
  286.                                 returnField = returnField.substring(0, returnField.length() - 1);
  287.                         }
  288.                        
  289.                 }
  290.                
  291.                 if(startOfSelect >= 0 && startOfFrom >= 0) {
  292.                         String selectFromStr = _sql.substring(startOfSelect + "select".length(), startOfFrom);
  293.                         String fromEndStr = _sql.substring(startOfFrom + "from".length(), _sql.length());
  294.                         selectFromStr = selectFromStr.trim();
  295.                         if(selectFromStr.length() > 0) {
  296.                                 String selectField = "";
  297.                                 String[] tempSqlArr = selectFromStr.split(",");
  298.                                 for(String tempStr : tempSqlArr) {
  299.                                         if(tempStr != null && tempStr.length() > 0) {
  300.                                                 if(tempStr.equalsIgnoreCase("*")) {
  301.                                                         selectField += returnField + ",";
  302.                                                 } else {
  303.                                                         selectField += tempStr + ",";
  304.                                                 }
  305.                                         }
  306.                                 }
  307.                                 if(selectField.length() > 0) {
  308.                                         selectField = selectField.substring(0,selectField.length() - 1);
  309.                                         return "select" + " " + selectField + " from " + fromEndStr;
  310.                                 }
  311.                         }
  312.                 }
  313.                
  314.                 return _sql;
  315.         }
  316.        
  317.         /**
  318.          * 数据库类型
  319.          * @author polarrwl
  320.          */
  321.         public enum dbtype {
  322.                 oracle,
  323.                 mysql,
  324.                 sqlserver,
  325.                 db2,
  326.                 hsql,
  327.                 kingbase
  328.         }
  329.        
  330.         /**
  331.          * 根据驱动得到对应的数据库类型
  332.          * @param _driver
  333.          * @return
  334.          */
  335.         public static dbtype getDbtypeByDriver(String _driver) {
  336.                 if(_driver != null) {
  337.                         if(_driver.toLowerCase().indexOf("oracle") >= 0) {
  338.                                 return dbtype.oracle;
  339.                         } else if(_driver.toLowerCase().indexOf("kingbase") >= 0) {
  340.                                 return dbtype.kingbase;
  341.                         } else if(_driver.toLowerCase().indexOf("mysql") >= 0) {
  342.                                 return dbtype.mysql;
  343.                         } else if(_driver.toLowerCase().indexOf("sqlserver") >= 0) {
  344.                                 return dbtype.sqlserver;
  345.                         } else if(_driver.toLowerCase().indexOf("hsql") >= 0) {
  346.                                 return dbtype.hsql;
  347.                         } else if(_driver.toLowerCase().indexOf("db2") >= 0) {
  348.                                 return dbtype.db2;
  349.                         }
  350.                 }
  351.                 return null;
  352.         }
  353.        
  354.         /**
  355.          * 设定当前的数据库类型
  356.          * @param _dbtype
  357.          */
  358.         public void setCurrentDialect(dbtype _dbtype) {
  359.                
  360.                 log.info("设定当前的数据库类型(currentDialect):" + _dbtype);
  361.                
  362.                 if(_dbtype != null) {
  363.                         currentDialect = _dbtype;
  364.                 }
  365.         }
  366.        
  367.         public static void main(String[] args) {
  368.                 System.out.println(genReturnField("select * from user order by type"));
  369.         }
  370. }
  371.  
  372. //java/6244

Reply to "Share a Java paging code for different databases"

Here you can reply to the paste above

captcha

https://burned.cc - Burn After Reading Website