亡羊补牢,为时未晚!!!

Posted on 2010-09-06 11:21 java小爬虫 阅读(1522) 评论(0)  编辑  收藏
    有这么一种场景,设计好的数据模型在有数据以后要修改数据模型。本文就是针对这个问题展开的。
    要增加,删除一列,这根本不是问题,关键是要修改一列。这需要考虑到那些问题呢?
    在java里面有类型转换,转换分为两种:自然转换和强制转换。自然转换就是把子类型转成父类型,强制转换就是把父类型转成子类型。在数据库里面也一样,当然还要包括长度的截短和加长。强制转换和截短会造成数据的不准确和异常,本文不考虑这个情况。
    那么,如何改变数据表的列类型呢?通过SQL语句直接操作数据库,当然能解决这个问题,可是,如何有很多张表都要修改呢?那不把人累死了!!!
 
    我就碰到了这么一个问题,加班加点的,写成了一个JAVA小程序,来自动实现我的要求。

    需求:把数据库中字段类型为blob和varchar2(4000)的数据表都修改为clob;

    问题解决思路:复制数据表结构和数据到一个临时表,先删除要修改的列,再创建同名不同类型的列,从原始表中查出这一列的数据,复制的临时表中,删除原始表,修改临时表名为原始表名。

    处理过程日志截图:


    代码思路及重要代码:
    1:获取系统所有的用户表:
             String sql = " select table_name from user_tables " ;
    2:获取表的主键(只考虑单主键) 
             String sql = "  select column_name from user_cons_columns " +
                        "  where constraint_name = (" +
                              "  select constraint_name from user_constraints " +
                                  " where table_name = upper('"+tableName+"') " +
                                      "and constraint_type = 'P'" +
                                          ")" ; 
    3:获取表中列信息:列名,类型 和长度。
             String sql = " select column_name,data_type,data_length from user_tab_columns  where table_name =  '"+ tableName+"'" ;   
    4:根据2和3,判断要修改的列,组织(主键和要修改的列信息)数据。
        代码片段:

        List<String[]> :装有要修改表的表名,主键,列信息(列名,类型,长度);List中,第一条数据为表名,第二条数据为主键,其余为要修改的列信息,String[]为变长数组;
   
String columnName="";
        String dataType
="";
        String dataLength
="";
        List
<String[]> result = new ArrayList<String[]>(3);
        result.add(
new String[]{tableName});
        String primaryKeyName 
= getPrimaryKey(tableName);
        
if(primaryKeyName.equals("")||primaryKeyName==nullreturn null ;
        result.add(
new String[]{primaryKeyName});
            
try {
                String sql 
= " select column_name,data_type,data_length from user_tab_columns  where table_name =  '"+ tableName+"'" ;    
                ResultSet resultSet 
= OracleDBUtil.executeQuery(sql);
                
while(resultSet.next()){
                    columnName
=resultSet.getString(1);
                    dataType
=resultSet.getString(2);
                    dataLength
=resultSet.getString(3);
                    
if(dataType.equals("BLOB")){
                        result.add(
new String[]{columnName,dataType});
                    }
else if((dataType.equals("VARCHAR2")&&Integer.parseInt(dataLength) >= Constant.varchar2_size)||(dataType.equals("VARCHAR")&&Integer.parseInt(dataLength) >= Constant.varchar2_size)){
                        result.add(
new String[]{columnName,dataType,dataLength});
                    }
                }
                resultSet.close();
            } 
catch (SQLException e1) {
                e1.printStackTrace();
            }
        
return result;
    5:取出4返回的信息,组织数据,启动修改流程;
for (List<String[]> table : tables) {
            
//tableInfo = tableInfo+  "\t表名:\t" ;
            tableInfo = "\t表名:\t" ;
            tableInfo 
= tableInfo+table.get(0)[0]+ "\t主键 :\t "+table.get(1)[0]+" \t字段 :\t ";
            String[] columns 
= new String[table.size()-2];
            
for (int i =2;i<table.size();i++) {
                
if(table.get(i)==nullbreak ;
                tableInfo 
= tableInfo+table.get(i)[0]+"  "+table.get(i)[1];
                
if(table.get(i).length == 3) tableInfo = tableInfo+ "("+table.get(i)[2]+")";
                tableInfo 
= tableInfo + "\t";
                String[] columnInfo 
= table.get(i) ;
                columns[i
-2]=columnInfo[0];
            }
            tableInfo 
= tableInfo+"\n";
            System.out.println(tableInfo);
            
            
            BufferedReader in 
= new BufferedReader(new InputStreamReader(System.in));
            String str 
= "";
                System.out.println(
"   是否修改,请输入'Y'或者'N' ! ");
                
try {
                    str 
= in.readLine();
                } 
catch (IOException e) {
                    e.printStackTrace();
                }
                
if(str.equalsIgnoreCase("y")){
                    blobOrVarchar2Clob(table.get(
0)[0],table.get(1)[0],columns);
                }
        }
        
        System.out.println(
"数据表修改处理逻辑结束!!!");

    6:修改流程:使用了门面模式,实现了“复制数据表结构和数据到一个临时表,先删除要修改的列,再创建同名不同类型的列,从原始表中查出这一列的数据,复制的临时表中,删除原始表,修改临时表名为原始表名。”构想。
    
public static boolean blobOrVarchar2Clob(String srcTableName, String srcTableIdName, String columnNames) {
        
if (srcTableName == null || srcTableName.equals("")
                
|| columnNames == null || columnNames.length == 0
                
|| srcTableIdName == null || srcTableIdName.equals(""))
            
return false;
        String printColumnNames 
= "" ;
        
for (String columnName : columnNames) {
            printColumnNames 
+= "  " +  columnName ;
        }
        System.out.println(
"马上就被修改  表名: "+srcTableName +  "   ,ID: " + srcTableIdName+"  字段:   "+printColumnNames);
        Utils.createTempTable(srcTableName);
        
for (String columnName : columnNames) {
            
if(columnName==null||columnName.equals(""))continue ;
            Utils.dropTempTableColumn(srcTableName, columnName);
            Utils.addTempTableClobColumn(srcTableName, columnName);
            Utils.copyDataOneColumn(srcTableName, columnName, srcTableIdName);
        }
        Utils.dropSrcTable(srcTableName
+"_");
//        Utils.dropSrcTable(srcTableName);
//        Utils.modifyTempTableToSrcTable(srcTableName);
        return true;
    }

    7:从原始表复制一列数据到临时表:将数据写入Map结构,再写入临时表。
      代码片断:
   
HashMap<Integer, String> map = new HashMap<Integer, String>();
    
            
try {
                
while(resultSet.next()){
                    String content 
= "";            
                        
int id = resultSet.getInt(srcTableIdName);
                        
                        
int columnIndex = resultSet.findColumn(columnName);
                         ResultSetMetaData resulSetMetaData 
= resultSet.getMetaData();
                         String columnTypeName 
=resulSetMetaData.getColumnTypeName(columnIndex);
                        
                         
if("VARCHAR2".equals(columnTypeName)||"VARCHAR".equals(columnTypeName)){
                             content 
= resultSet.getString(columnName);
                         }
else if("BLOB".equals(columnTypeName)){
                                Blob blob 
= resultSet.getBlob(columnName);
                                
if(blob==null)continue;
                                content 
= Utils.readBlobToString(blob);
                         }
                        map.put(id, content);
                }
                resultSet.close();
            } 
catch (SQLException e1) {
                e1.printStackTrace();
            }
        
        Set
<Entry <Integer,String> > set = map.entrySet();
        Iterator
<Entry<Integer, String>> iterator =set.iterator();
        
while(iterator.hasNext()){
            Entry
<Integer, String> entry = iterator.next();
        sql 
= " update " + srcTableName + "" + " set "
            
+ columnName + " = ? where " + srcTableName + "_."
            
+ srcTableIdName + " = ? "  ;
        PreparedStatement pstatement 
=OracleDBUtil.getPreparedStatement(sql);
        
try {
            pstatement.setString(
1, entry.getValue());
            pstatement.setInt(
2, entry.getKey());
            OracleDBUtil.executeUpdate(pstatement);
            pstatement.close();




只有注册用户登录后才能发表评论。


网站导航: