程序员之家 >> 文章 >> .Net技术 >> ADO.NET
Java 实现 ADO.NET DataTable
作者:   来源:javaeye博客   发布者:admin
时间:2009-05-11 10:02:47   点击:1793

 Java 没有 DataTable(有吗?这个应该有,这个真没有),.net 的 System.Data 名字空间基本实现了一个内存数据库的功能,功能的却很强,
他们的实现我反编译源代码看了,不过没看太懂好像是用的数据库的索引原理不是我这样循环实现的查询。

   现在只有.net 移植 java 的开源项目象NHibernate NUnit log4n , 为什么java 就不能移植 .net 的优秀功能呢,java 社区的人也应该谦虚些啊。

   我这个实现的不好,希望能抛砖引玉激发 java 高手开始移植 .net 的优秀功能。请高手提出意见,如果没有人愿意做我想自己实现一个 java 的 System.Data

附件是 DataTable 的部分代码 , NetBeans 项目
 


package system.data;

import java.util.HashMap;
import java.util.ArrayList;
import java.util.ListIterator;
import system.Convert;

/***
 * DataTable 是 DataRow 的列表集合,并且其中包含了一个列名和列索引的哈希表
 * @author Fred
 */
public class DataTable extends ArrayList<DataRow>
{
    public HashMap<Object,Integer> column_index_map;
    public int column_count;

    public DataTable()
    {
        this.column_index_map = new HashMap<Object,Integer>();
        this.column_count = 0;
    }

    /***
     * 将一列的所有记录转化为一个数组
     * @param field 投影的列名
     * @return
     */
    public Object[] collect(String field)
    {
        if(this.size()==0)
            return null;

        HashMap map = new HashMap();
        ListIterator<DataRow> iter = this.listIterator();

        while(iter.hasNext())
            map.put(iter.next().get(field), null);
       
        return map.keySet().toArray();
    }
 
    /***
     * 将当前表的每一行与FieldHashDataRow用foreign_key关联
     *  fDataRow 必须是以foreign_key为键的Hashtable
     *  用这个方法有一个限制是两个表中同名的字段必须具有同样的含义,不同名的字段具有不同的含义。
     * @param fDataRow
     * @param foreign_key
     */
    public void join(FieldHashDataRow fDataRow,String foreign_key)
    {
        if(fDataRow==null)
            return;

        int size = this.size();

        for(int i=0;i<size;i++)
        {
            DataRow dr = this.get(i);
            DataRow pdr = fDataRow.get(dr.get(foreign_key));
            dr.join(pdr);
        }
    }

    public void addColumn(String name)
    {
        this.column_index_map.put(name, this.column_count++);
    }

    public DataRow newRow()
    {
        return new DataRow(this);
    }

    /***
         * 实现简单的内存 SQL 表达式
         * @param expression
         * @return
         */
    public ArrayList<DataRow> select(String expression)
    {
        Expression e = Expression.FindExpression(expression);
        ArrayList<DataRow> list = new ArrayList<DataRow>();

        for(DataRow row : this)
          if(e.eval(row))
              list.add(row);
        return list;
    }
}

//<editor-fold defaultstate="collapsed" desc="Expression">
class Expression
{
 private String expression;
 private int exp_len;
 private char[] exp_array;
 private ArrayList<String> token_list;
    private boolean is_flushed;
    private char c;
 private StringBuffer sb;
 private int cur_token_index;
 private int token_count;

 public Expression(String expression)
 {
  this.expression = expression;
  this.exp_len = expression.length();
  this.exp_array = expression.toCharArray();
  this.token_list = new ArrayList<String>();
  this.is_flushed = true;
  this.cur_token_index = -1;
  this.sb = new StringBuffer();
  this.initTokenList();
  this.token_count = this.token_list.size();

 }

 private void flush()
 {
  if(this.is_flushed)
   return;

  this.token_list.add(this.sb.toString());
  this.sb = new StringBuffer();
  this.is_flushed = true;
 }

 private void collect()
 {
  this.sb.append(c);
        this.is_flushed = false;
 }

 private boolean nextToken()
 {

  if(this.cur_token_index<this.token_count-1)
  {
   this.cur_token_index++;
   return true;
  }

  return false;
 }

 private String currentToken()
 {
  return this.token_list.get(this.cur_token_index);
 }

    private void initTokenList()
    {
     for(int i=0;i<this.exp_len;i++)
     {
      c = exp_array[i];
      if(Character.isWhitespace(c))
            {
                this.flush();
                continue;
            }

            switch(c)
            {
             case '<' :

              this.flush();
              if(i+1<this.exp_len && exp_array[i+1]=='=')
                    {
                        this.token_list.add("<=");
                        i++;
                    }
                    else
                    {
                     this.token_list.add("<");
                    }
              break;

             case '>' :

              this.flush();
              if(i+1<this.exp_len && exp_array[i+1]=='=')
                    {
                        this.token_list.add(">=");
                        i++;
                    }
                    else
                    {
                     this.token_list.add(">");
                    }
              break;

             case '(' :

              this.flush();
              this.token_list.add("(");
              break;

             case ')' :

              this.flush();
              this.token_list.add(")");
              break;

             case '=' :

              if(i+1<this.exp_len && exp_array[i+1]=='=')
              {
               this.flush();
               this.token_list.add("==");
               i++;
              }
              else
              {
               this.collect();
              }
              break;

             case '!' :

              if(i+1<this.exp_len && exp_array[i+1]=='=')
              {
               this.flush();
               this.token_list.add("!=");
               i++;
              }
              else
              {
               this.collect();
              }
              break;


             default:

              this.collect();
              break;
            }
     }

     this.flush();
    }

    public boolean eval(DataRow dr)
    {
     this.nextToken();
     boolean result = this.doAndOr(dr);
        this.cur_token_index = -1;
        return result;
    }

    private boolean doAndOr(DataRow dr)
    {
     boolean result = this.doNot(dr);
     String op = "";

        boolean result_right;

     while((op=this.currentToken()).equals("and") || op.equals("or"))
     {
      this.nextToken();

      if(op.equals("and"))
            {
                result_right = this.doNot(dr);
       result = result && result_right;
            }
      else
            {
                result_right = this.doNot(dr);
       result = result || result_right;
            }
     }

     return result;
    }

    private boolean doNot(DataRow dr)
    {
     String op="";

     if((op=this.currentToken()).equals("not"))
      this.nextToken();

     boolean result = this.doBrackets(dr);

     if(op.equals("not"))
       return !result;

     return result;
    }

    private  boolean doBrackets(DataRow dr)
    {
     boolean result;
     if(this.currentToken().equals("("))
     {
      this.nextToken();
      result = this.doAndOr(dr);
      this.nextToken();
     }
     else
     {
      result = this.doCompare(dr);
     }

     return result;
    }

    private boolean  doCompare(DataRow dr)
    {
     Object field = dr.get(this.currentToken());
     this.nextToken();
     String opt = this.currentToken();
     this.nextToken();
     String value = this.currentToken();
        this.nextToken();

     if(opt.equals("like"))
     {
      return isLike(field,value);
     }
     else if(opt.equals(">"))
     {
      return isGreat(field,value);
     }
        else if(opt.equals("<"))
     {
      return isLess(field,value);
     }
     else if(opt.equals("=="))
     {
      return isEquals(field,value);
     }
        else if(opt.equals(">="))
     {
      return isGreatEquals(field,value);
     }
        else if(opt.equals("<="))
     {
      return isLessEquals(field,value);
     }
        else if(opt.equals("!="))
        {
            return isNotEquals(field,value);
        }

     return false;

    }
   

//<editor-fold  defaultstate="collapsed" desc="tool method">

    private static boolean isLike(Object field,String value)
    {
     int len = value.length();
  if(value.startsWith("'%") && value.endsWith("%'"))
   return Convert.toString(field).contains(value.substring(2,len-2));
  else if(value.startsWith("'%"))
   return Convert.toString(field).endsWith(value.substring(2,len-1));
  else if(value.endsWith("%'"))
   return Convert.toString(field).startsWith(value.substring(1,len-2));
  else
   return Convert.toString(field).equals(value.substring(1,len-1));
    }

    private static boolean isLess(Object field,String value)
    {
     if(field instanceof Number)
            return Convert.toFloat(field)<Convert.toFloat(value);
        return Convert.toString(field).compareTo(value.substring(1,value.length()-1))<0;
    }

    private static boolean isGreat(Object field,String value)
    {
        if(field instanceof Number)
            return Convert.toFloat(field)>Convert.toFloat(value);
        return Convert.toString(field).compareTo(value.substring(1,value.length()-1))>0;
    }

    private static boolean isEquals(Object field,String value)
    {
         if(value.equals("null"))
            return field==null;

        if(field instanceof Number)
            return Convert.toFloat(field)==Convert.toFloat(value);
        if(field instanceof Boolean)
            return Convert.toBool(field)==Convert.toBool(value);

        return Convert.toString(field).equals(value.substring(1,value.length()-1));
    }

    private static boolean isNotEquals(Object field,String value)
    {
        if(value.equals("null"))
            return field!=null;

        if(field instanceof Number)
            return Convert.toFloat(field)!=Convert.toFloat(value);
        if(field instanceof Boolean)
            return Convert.toBool(field)==Convert.toBool(value);

        return !Convert.toString(field).equals(value.substring(1,value.length()-1));
    }

    private static boolean isLessEquals(Object field,String value)
    {
     if(field instanceof Number)
            return Convert.toFloat(field)<=Convert.toFloat(value);
        return Convert.toString(field).compareTo(value.substring(1,value.length()-1))<=0;
    }

    private static boolean isGreatEquals(Object field,String value)
    {
        if(field instanceof Number)
            return Convert.toFloat(field)>=Convert.toFloat(value);
        return Convert.toString(field).compareTo(value.substring(1,value.length()-1))>=0;
    }
//</editor-fold>

    private static HashMap<String,Expression> expression_map = new HashMap<String,Expression>();

    public static Expression FindExpression(String expression)
    {
        Expression e = expression_map.get(expression);
        if(e==null)
        {
            e = new Expression(expression);
            expression_map.put(expression, e);
        }
        return e;
    }
   
}
 //</editor-fold>


 ///////////////////////////////////////////////// ///////////////////////////////////////////////// /////////////////////////////////////////////////


 package system.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import system.Convert;

/***
 * DataRow 由一个DataTable 创建而来,
 * DataRow 实际是一个列表,DataRow 从 DataTable 中获得列名和索引的对应关系并实现Map 接口实现按列取值
 * 这个结构不应该单独存在只作为DataTable 的子项
 * @author Fred
 */
public class DataRow implements Map
{
    private ArrayList fields;
    private DataTable parentTable;
    private int column_count;

    /***
     *  这个方法不应该被程序员调用
     * @param dTable
     */
    public DataRow(DataTable dTable)
    {
        this.fields = new ArrayList();
        this.parentTable = dTable;
        this.column_count=0;
    }

    /***
     *  将另外一张表的一行的列数据补充到当前行的已有列中
     * @param dr
     * @return 当前行(已经补充完数据的)
     */
    public DataRow join(DataRow dr)
    {
        if(dr==null)
            return this;
        Set<String> key_set = dr.keySet();
        //dr 的所有key 覆盖到当前行的所有同名key中
        for(String k : key_set)
            this.put(k, dr.get(k));
        return this;
    }

    /***
     * 给 ArrayList 表示的行数据按照列索引设置值
     * 注意如果当前列索引超出了 ArrayList  最后一个元素的索引下标,则将缺失的所有元素用空补上。
     * @param key 列名
     * @param value 列值
     * @return 设置前列的旧值
     */
    public Object put(Object key, Object value)
    {
        Integer column_index = this.parentTable.column_index_map.get(key);
        if(column_index==null)
         return null;
       
        int j = column_index.intValue();
        while(this.column_count<j+1)
        {
         this.fields.add(null);
         this.column_count++;
        }

        this.fields.set(j,value);
        return null;
    }

    public Object get(Object key)
    {
        Integer column_index = this.parentTable.column_index_map.get(key);
        if(column_index==null)
         return null;
         int j = column_index.intValue();

         if(j<this.column_count)
            return this.fields.get(j);
         return null;
    }

    //<editor-fold defaultstate="collapsed" desc="only_for_implements_Map">
    public String getString(Object key)
    {
        return Convert.toString(get(key));
    }

    public int getInt(Object key)
    {
        return Convert.toInt(get(key));
    }

    public float getFloat(Object key)
    {
        return Convert.toFloat(get(key));
    }

    public Date getDate(Object key)
    {
        return Convert.toDate(get(key));
    }

    public void clear()
    {
        this.fields.clear();
    }

    public boolean containsKey(Object key)
    {
        return this.parentTable.column_index_map.containsKey(key);
    }

    public boolean containsValue(Object value)
    {
        return this.parentTable.column_index_map.containsValue(value);
    }

    public Set entrySet()
    {
        return this.parentTable.column_index_map.entrySet();
    }

    public boolean isEmpty()
    {
        return this.fields.isEmpty();
    }

    public void putAll(Map m)
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Object remove(Object key)
    {
        Integer column_index = this.parentTable.column_index_map.get(key);
        if(column_index==null)
         return null;

         int j = column_index.intValue();
         return this.fields.remove(j);
    }

    public int size()
    {
        return this.parentTable.column_count;
    }

    public Set keySet()
    {
        return this.parentTable.column_index_map.keySet();
    }
   
    public Collection values()
    {
         return this.parentTable.column_index_map.values();
    }
    //</editor-fold>
}

最新文章
点击排行