package com.ycsoft.report.query.redis; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.List; import com.ycsoft.commons.exception.ReportException; import com.ycsoft.commons.helper.LoggerHelper; import com.ycsoft.report.commons.ReportConstants; import com.ycsoft.report.db.ConnContainer; import com.ycsoft.report.query.daq.translate.CacheHeadCell; import com.ycsoft.report.query.daq.translate.CacheKey; /** * 调用存储过程创建一张临时表 * 把CacheKey数据写入数据库 * 调用存储过程分析新建的临时表 * <p> * */ public class CacheKeySortByDB { /** * 是否发生异常 */ private boolean work_error=false; //排序用表名 private String sorttabname=null; public enum WorkMode{ READ,WRITE; } private WorkMode mode; private String writesql=null; private int no_crosshead_start=0; //哪个id列是带有字段 private boolean[] field_is_sort=null; private String query_id=null; public CacheKeySortByDB(int no_crosshead_start,String query_id){ this.no_crosshead_start=no_crosshead_start; this.query_id=query_id; } /** * 打开读取工作模式 * @param headlist * @param no_crosshead_start * @param sorttab * @throws ReportException */ public void openReadMode() throws ReportException{ if(this.mode==null||WorkMode.READ.equals(this.mode)){ throw new ReportException("cannot open read_mode"); } this.mode=WorkMode.READ; this.readModeInit(); } /** * 读取模式初始化 * select f0,f1,f2,f3 from r_12312 order by f0,to_number(f1),f2,f3 * @throws ReportException */ private void readModeInit() throws ReportException{ try { //生成读取语句 StringBuilder selectsql=new StringBuilder(); StringBuilder orderbysql=new StringBuilder(); selectsql.append("select "); int f_idx=0; for(int i=0;i<no_crosshead_start;i++){ if(i==0){ selectsql.append(" f").append(f_idx); }else{ selectsql.append(",f").append(f_idx); } f_idx++; //排序字段 if(this.field_is_sort[i]){ orderbysql.append(",to_number(f").append(f_idx).append(")"); f_idx++; } } selectsql.append(" from ").append(this.sorttabname).append(" order by ").append(orderbysql.toString().substring(1, orderbysql.length())); if(this.read_conn==null){ read_conn=ConnContainer.getConn(ReportConstants.DATABASETYPE_CUBE_SORT); read_conn.setAutoCommit(false); } if(this.read_ps!=null){ throw new ReportException("PreparedStatement has open."); } String sql=selectsql.toString(); LoggerHelper.debug(this.getClass(), sql); this.read_ps=read_conn.prepareStatement(sql); this.read_ps.setFetchSize(1000); this.read_rs=this.read_ps.executeQuery(); } catch (Exception e) { this.work_error=true; throw new ReportException("数据库错误",e); } } private ResultSet read_rs=null; private PreparedStatement read_ps=null; private Connection read_conn=null; /** * 读取一批key * @throws ReportException */ public RedisCacheKey readCacheKey() throws ReportException{ try { RedisCacheKey key=null; if(this.read_rs.next()){ List<Object> list=new ArrayList<Object>(); List<Integer> sort=new ArrayList<Integer>();//伪造的排序 for(int i=1;i<=this.no_crosshead_start;i++){ list.add(read_rs.getString(i)); sort.add(i); } key=new RedisCacheKey(list,sort,this.query_id); } return key; } catch (Exception e) { this.work_error=true; throw new ReportException(e); } } /** * 打开写入工作模式 * @param key * @throws ReportException */ public void openWriteMode() throws ReportException{ if(WorkMode.WRITE.equals(this.mode)){ return; }else if(WorkMode.READ.equals(this.mode)){ throw new ReportException("is read_mode"); }else{ this.mode=WorkMode.WRITE; } this.writeModeInit(); } /** * 写入一组键值 * @param keys * @throws SQLException * @throws ReportException */ public void writeCacheKey(List<CacheKey> keys) throws ReportException{ if(keys==null||keys.size()==0) return; Connection conn=null; PreparedStatement ps=null; try{ conn=ConnContainer.getConn(ReportConstants.DATABASETYPE_CUBE_SORT); ps=conn.prepareStatement(this.writesql); for(CacheKey key:keys){ int field_idx=1; for(int i=0;i<this.no_crosshead_start;i++){ String id=key.getKeys().get(i).toString(); ps.setString(field_idx,id); field_idx++; if(this.field_is_sort[i]){ ps.setString(field_idx,key.getSorts().get(i).toString()); field_idx++; } } ps.addBatch(); } ps.executeBatch(); conn.commit(); }catch (Exception e) { this.work_error=true; try { conn.rollback(); } catch (Exception e1) {} throw new ReportException(e); }finally{ if(ps!=null){ try { ps.close(); } catch (SQLException e) { } ps=null; } if(conn!=null){ try { conn.close(); } catch (SQLException e) { } conn=null; } } } /** * 写入模式初始化 * 计算字段长度,cube_cache_key的临时排序表的字段数量, * 一个表头对应一个字段,如果一个表头开始了自动以排序功能,则多占一个字段用于排序 * 如果维度的一个层启用了排序,通过在数据库建表实现排序; * 调用数据库存储过程,实现建表和删表 * @throws ReportException */ private void writeModeInit() throws ReportException{ CallableStatement cs=null; Connection conn=null; try{ //分析字段数和哪个id对应有排序 int fields=0; field_is_sort=new boolean[no_crosshead_start]; for(int i=0;i<this.no_crosshead_start;i++){ field_is_sort[i]=true; } fields=no_crosshead_start*2; if(conn==null){ conn=ConnContainer.getConn(ReportConstants.DATABASETYPE_CUBE_SORT); conn.setAutoCommit(false); } //调用存储过程创建表 //参数1字段,参数2返回表名,参数3错误内容 cs=conn.prepareCall("{call proc_repsort_create(?,?,?) }"); cs.setInt(1,fields ); cs.registerOutParameter(2, Types.VARCHAR); cs.registerOutParameter(3, Types.VARCHAR); cs.executeUpdate(); conn.commit(); sorttabname=cs.getString(2); LoggerHelper.debug(this.getClass(),sorttabname); String error=cs.getString(3); if(error!=null&&error.trim().length()>0){ this.work_error=true; throw new ReportException("CUBE排序调用proc_repsort_create错误:"+error); } // insert into r_1231(f1,f2,f3) values (?,?,?) //生成写入SQL语句 StringBuilder writesql=new StringBuilder(); writesql.append("insert into ").append(sorttabname).append("(f0"); for(int i=1;i<fields;i++){ writesql.append(",f").append(i); } writesql.append(")values(?"); for(int i=1;i<fields;i++){ writesql.append(",?"); } writesql.append(")"); this.writesql= writesql.toString(); }catch(ReportException e){ this.work_error=true; throw e; }catch(Exception e){ this.work_error=true; try { conn.rollback(); } catch (SQLException e1) {} throw new ReportException("CUBE排序调用proc_repsort_create错误",e); }finally{ if(cs!=null){ try { cs.close(); } catch (Exception e) {} } if(conn!=null){ try { conn.close(); } catch (Exception e) { } } } } /** * 删除新建的排序用表 * @throws ReportException */ private void dropSortTab() { CallableStatement cs=null; Connection conn=null; try { if(conn==null){ conn=ConnContainer.getConn(ReportConstants.DATABASETYPE_CUBE_SORT); conn.setAutoCommit(false); } //调用存储过程创建表 cs=conn.prepareCall("{call proc_repsort_drop(?) }"); cs.setString(1, this.sorttabname); cs.executeUpdate(); conn.commit(); } catch (Exception e) { LoggerHelper.error(this.getClass(), "drop sort_tab error", e); }finally{ if(cs!=null){ try { cs.close(); } catch (Exception e) {} } if(conn!=null){ try { conn.close(); } catch (Exception e) {} } } } public void close() { //发生异常或者读取模式结束,删除临时排序表 if(this.work_error||WorkMode.READ.equals(this.mode)){ this.dropSortTab(); } if(read_rs!=null){ try { read_rs.close(); } catch (SQLException e) { } read_rs=null; } if(read_ps!=null){ try { read_ps.close(); } catch (SQLException e) { } read_ps=null; } if(read_conn!=null){ try { read_conn.close(); } catch (SQLException e) { } read_conn=null; } } }