如鹏网 大学生计算机学习社区

CowNew开源团队

http://www.cownew.com 邮件请联系 about521 at 163.com

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  363 随笔 :: 2 文章 :: 808 评论 :: 0 Trackbacks

#

1、从TextEditor继承,调用setSourceViewerConfiguration,并传进去一个从SourceViewerConfiguration 继承的配置类,就可以实现各种代码editor。
2、swt尽量使用GridLayout布局(不是java.awt中的GridLayout,而是swt中的)和GridData域。文章:http://coolbear.yculblog.com/post.89429.html

3、得到文件的编辑器的方法:
    public static IEditorPart findEditor(IFile file){
        IEditorReference[] editors = getActivePage().getEditorReferences();;
        for (int i = 0; i < editors.length; i++) {
            IEditorPart part = (IEditorPart)editors[i].getPart(false);
            if (part != null ){
                IEditorInput input = part.getEditorInput();
                if(input instanceof FileEditorInput && ((FileEditorInput)input).getFile().equals(file))
                    return part;
            }               
        }
        return null;
    }

4、得到工作区中所有工程的方法:
        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
                .getProjects();
这在开发自己的工程向导的时候很有用处。
5、工程特有文件判断方法
project.getFile("cownew.prj").exists();
project.getDescription().hasNature();
给工程增加Nature的方法:
 IProjectDescription desc = project.getDescription();
String[] oldNatureIds = desc.getNatureIds();
                String[] newNatureIds  = new String[oldNatureIds.length +1];
                System.arraycopy(oldNatureIds, 0, newNatureIds, 0, oldNatureIds.length);
                newNatureIds[oldNatureIds.length] = "CowNewNature";
                desc.setNatureIds(newNatureIds);
                project.setDescription(desc, monitor);
6、创建文件夹的方法:
IFolder folder = project.getFolder("myfold");
if (folder!=null && !folder.exists())
  folder.create(false, true, null);

7、弹出包选择对话框的方法:
ElementListSelectionDialog dialog = new ElementListSelectionDialog(
                    getShell(), new LabelProvider());
            dialog.setIgnoreCase(false);
dialog.setElements(getAllPackages().toArray());
            String path = currentPackage();
 dialog.setInitialSelections(new Object[] { path });
dialog.open();
fPKName.setText((String) dialog.getFirstResult());

public List getAllPackages() {
        List list = new ArrayList();
        IResource res = getFirstSelection();
        IProject project = res.getProject();
        File file = project.getFolder("src").getLocation().toFile();
        File[] fs = file.listFiles();
        for (int i = 0; i < fs.length; i++) {
            if (fs[i].isDirectory())
                iterator("", fs[i], list);
        }
        Collections.sort(list);
        return list;
    }
8 objectClass="org.eclipse.core.resources.IFile"代表菜单应用到文件
9 透视图的的实现很简单,就是在构造函数里边打开一些视图,使一些action(这样菜单和按钮也就都可用)可以用,比如:
String editorArea = layout.getEditorArea();
        IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
                0.30f, editorArea);
        left.addView(PACKAGE_VIEW_ID);
 layout.setEditorAreaVisible(true);
 layout.addShowViewShortcut(IDESystem.BUSINESSVIEW_ID);

posted @ 2006-07-21 00:33 CowNew开源团队 阅读(1274) | 评论 (1)编辑 收藏

为了帮助更多的朋友掌握eclipse的使用,我们团队做了一个eclipse视频教程,全部都是开发过程的屏幕录像,并且伴有语音讲解。一共八讲,今天全部上传完毕。希望我们的努力帮助更多的朋友。
观看方式:
1、登录硅谷动力在线观看:http://www.enet.com.cn/article/2006/0704/A20060704124810.shtml
2、通过cownew团队网站中的超链接访问:
http://www.cownew.com/kc/

感谢大家的支持。
附前四讲课件:
          第一讲  eclipse的基本使用
1、eclipse工程的建立
2、源文件夹等概念
3、基本代码的编写
             第二讲  eclipse基本操作(1)
1、建立包、建立接口 及其他  
2、工程的高级配置   
3、工程的构建
3、代码的自动完成、自动修正功能
   黄色的、红色的标识
   (1)方法的自动生成
   (2)导入import
   (3)清除无用的import
   (4)自动清除无用的方法、变量
   (5)自动实现接口的、抽象类的方法,自动重载父类方法
         第三讲   eclipse基本操作(2)
1、Java的调试
    (1) 断点、条件断点、异常断点
   (2)断点中变量的查看,语句的执行
2、智能纠错、自动完成:
   (1)自动生成try...catch,自动列出异常列表,自动转型...在红色提示上点击鼠标,常常可以得到惊喜
   (2)自动生成set、get方法
   (3)自动生成构造函数, 
   (4)javadoc的自动生成

第四讲 eclipse高级操作(1) 重构
一、概述
1、好的程序应该是不断重构出来的。消除bad smell,提高代码可读性、可维护性和可扩展性。《重构-改善既有代码的设计》(英文名《Refactoring: Improving the Design of Existing Code 》)
2、Eclipse的自动重构功能能够很好地支持各种程序元素的重命名,并自动更新相关的引用。Eclipse能够支持方法、字段在类之间移动,并自动更新引用。Eclipse较好地支持内联字段、函数的更新替换。Eclipse较好地支持抽取方法、变量等程序元素。
3、Eclipse的重构支持撤销和重做,并且能够预览重构结果,会对有可能导致错误的重构结果进行提示。所以使用Eclipse进行重构是非常安全的。
二、重构不高深-实战重构
1、方法抽取 Extract Mehod:
将caclCost中参数校验部分抽取成方法verify。
2、重命名 Rename
  (1)重命名类名Test1为CostCalculator。
  (2)重命名User为UserInfo
3、内联 Inlining
   内联方法add
4、常量抽取 Extract Constant:
   将"normal"、"vip"抽取成常量
5、抽取局部变量 Extract Local Variable
   将user.userType抽取成变量
6、包装字段 Encapsulate Field
   重构User类,用set get包装
7、Extract Interface 抽取接口
   CostCalculator中抽取ICostCalculator接口
posted @ 2006-07-19 23:55 CowNew开源团队 阅读(1791) | 评论 (3)编辑 收藏

类型转化

Java是一种强类型语言,每个实例都必须有指定的类型。实际上,Java类型有两种声明类型运行时类型 (也可以相应的说是静态类型动态类型 ). 像Python这样的弱类型语言通常称为无类型,但是这样说并不严谨,因为每个实例都有它的运行时类型。你只是不用事先声明一个实例的类型而已。

要想调用一个对象中的方法,这个方法需要在声明类型中存在。也就是说,你只能调用定义在父类中的方法,即使该实例是一个确定的子类型:

List list = new ArrayList();
list.add("data");       // 在这里没问题
list.ensureCapacity(4); // 这里就不行了ensureCapacity() 只在ArrayList中才有。

如果我们要调用实际类型中的方法,我们首先要将它转为正确的类型。在本例中,我们可以把 ArrayList 转为List,因为ArrayList实现了List 接口. 也可以在运行时动态的检验,使用 list instanceof ArrayList.

可扩展的接口

糟糕的是,一个类不能总是实现你所需要实现的接口。可能是因为这只对少数几种情况才有效,或者它是一个没有被关联的库中的类型,或者这个接口在后期又被改变了。

这种情况就可以使用IAdaptable。 你可以把 IAdaptable 动态的进行类型转化。使用如下方法避免直接的类型转化:

Object o = new ArrayList();
List list = (List)o;

我们可以这样做:

IAdaptable adaptable = new ArrayList();
List list = (List)adaptable.getAdapter(java.util.List.class);

你可认为它是一种类型动态转化; 我们把adaptable转为List实例。

为什么不直接转化,而要用额外的getAdapter() 呢?这种机制可以使我们将目标类转化为没有实现的接口。例如, 我们可能想使用HashMap 作为一个 List, 尽管他们并不兼容。

IAdaptable adaptable = new HashMap();
List list = (List)adaptable.getAdapter(java.util.List.class);

实现IAdaptable

大多数IAdaptable的实现看起来就想是为支持类型构造多个if表达式的叠加。如果要为HashMap实现getAdapter() 可以这样:

public class HashMap implements IAdaptable {
  public Object getAdapter(Class clazz) {
    if (clazz == java.util.List.class) {
      List list = new ArrayList(this.size());
      list.addAll(this.values());
      return list;
    }
    return null;
  }
  // ...
}

返回的是一个对自身的代理,而不是直接转化类型。如果请求的是不支持的类型,可以直接返回null表明失败,这样比抛出异常要好。

PlatformObject

当你想添加新的要扩展的类型时,只是简单的修改一下就可以了。在任何情况下,如果已经得到了类型,为什么不修改接口?不修改类(如果使用接口,不容易保证向后兼容)或者改变它的类型(HashMap不是 List,但是可以转化)是有原因的。要解决这个问题,在Eclipse中,使用了一个抽象类 HashMap is not a List, but can be conveted into one).

To solve this problem, there's an abstract class that is used by most parts of Eclipse called -->PlatformObject。它为你实现了 IAdaptable接口,你就可以不用再操心了。

PlatformObject 代理所有的它对getAdapter()的请求到 IAdapterManager. IAdapterManager是平台默认提供的,通过 Platform.getAdapterManager()来访问。你可以将它想象为一个巨大的 Map ,它负责关联类和适当的适配器。PlatformObjectgetAdapter() 方法可以访问到这个Map.

适配已存在的类

这样的好处是可以为每一个PlatformObject对象动态的关联新的适配器,而不用重新编译。在Eclipse中的很多地方都是这样来支持扩展的。

这里希望将装有StringList转为XML节点。 XML节点显示为:

<List>
  <Entry>First String</Entry>
  <Entry>Second String</Entry>
  <Entry>Third String</Entry>
</List>

因为ListtoString方法可能有别的用途,所以不能使用。 可以为List添加一个工厂,当有转为XML节点的请求时,一个Node对象就会自动返回。

这里需要3个步骤:

1. 从List中生成Node

使用IAdapterFactory 来封装转换机制:

import nu.xom.*;
public class NodeListFactory implements IAdapterFactory {
  /** The supported types that we can adapt to */
  private static final Class[] types = {
    Node.class,
  };
  public Class[] getAdapterList() {
    return types;
  }
  /** The actual conversion to a Node */
  public Object getAdapter(Object list, Class clazz) {
    if (clazz == Node.class && list instanceof List) {
      Element root = new Element("List");
      Iterator it = list.iterator();
      while(it.hasNext()) {
        Element item = new Element("Entry");
        item.appendChild(it.next().toString());
        root.appendChild(item);
      }
      return root;
    } else {
      return null;
    }
  }
}

2. 注册工厂到PlatformAdapterManager

我们需要注册工厂到适配器工厂,当我们向 List实例请求Node时, 它就会知道是使用我们注册的工厂。 Platform为我们管理IAdapterManager ,而且注册过程相当简单:

Platform.getAdapterManager().registerAdapters(
  new NodeListFactory(), List.class
);

上面的代码要求平台管理者关联NodeListFactoryList。但我们要求List实例的适配器,它会调用这个工厂。根据我们对工厂的定义,会获得一个Node对象。在Eclispe中,这一步必须在插件启动的时候显式的执行,要隐式执行可以通过 org.eclipse.core.runtime.adapters 扩展点。

3. 向List要求Node

这里是要求适配器返回一个 Node 对象:

Node getNodeFrom(IAdaptable list) {
  Object adaptable = list.getAdapter(Node.class);
  if (adaptable != null) {
    Node node = (Node)adaptable;
    return node;
  }
  return null;
}

总结

如果你要在运行时为已存在的类添加功能,只要定义一个能完成转换功能的工厂,然后注册工程到 PlatformAdapterManager就可以了. 这项功能可以用来为一个非UI组件注册一个指定的UI组件,同时保持两部分的完全分离。就像在org.rcpapps.rcpnews.uiorg.rcpapps.rcpnews 插件中的使用。在这些例子中, IPropertySource 在UI插件中,它需要与非UI插件的数据相关联。当UI插件初始化时,它注册IPropertySourcePlatform, 当数据对象在浏览器中被选中时,属性视图中就会显示相应的属性。

很明显, java.util.List不能扩展PlatformObject, 所以你不能指望例子中的代码能够编译通过,你可以重新构造 List的子类来实现目的.继承PlatformObject 也不是必须的:

public class AdaptableList implements IAdaptable, List {
  public Object getAdapter(Class adapter) {
     return Platform.getAdapterManager().getAdapter(this, adapter);
  }
  private List delegate = new ArrayList();
  public int size() {
    return delegate.size();
  }
  // ...
}

本例中使用了XOM 来生成XML。

from:
http://www.javathink.org/bbs/read.php?tid-1469-page-e.html

posted @ 2006-07-19 21:49 CowNew开源团队 阅读(353) | 评论 (0)编辑 收藏


CowNew开源团队网站 http://www.cownew.com
作者 杨中科 是CowNew开源团队发起人之一,邮箱about521  at 163 dot com
论坛 http://www.cownew.com/newpeng/
转载请注明此版权信息


   最近准备把进销存项目激活,这样一方面可以让更多的人有机会参与到开源开发中来,另一方面也把SQL翻译器、SQL优化器、JDBMonitor应用到这个项目中,这样这三个基础模块就可以在实际项目应用中得到验证和增强。
    我准备用hibernate实现持久层,于是到hibernate的网站上把hibernate3下载下来,看了看有个hibernatetools,是个hibernate在eclipse下的辅助工具,也down了下来,用了用感觉不错。可以直接从数据库表生成POJO和hbm.xml(其实我不是很喜欢这种开发方式,我更喜欢我用建模工具来写POJO,然后用工具生成hbm.xml和DDL,不过好像hibernate3现在还没有这种工具,如果哪位朋友知道有这种工具,希望赐教)。
美中不足的是它生成的javabean的字段名是完全和数据库字段名一致、生成的javabean的类名是完全和数据库表名一致。出于清晰以及可移植的考虑(也是公司的开发规范养成的习惯),我设计的表名全部以"T_"开头,中间再加上子系统名,最后才是表意的表名,比如用“T_PS_BOM”表示生产管理系统中的物料清单表;字段名全部以“F”开头,比如FId,FName。
这样就导致生成了如下的javabean:

public class TPSBOM
{
   .......
   public String getFID()
   ...
   public String getFNumber()
}


    看起来很不直观。我刚刚想放弃这个工具,想了想,“拿来就用,不好用就换”可不是做开源人该有的精神呀。钻研一下。
看看了Hibernate Code Generation页签中有一个“reveng Strategy”,什么意思?“反向工程策略”??好像有门儿,点击“Browse”弹出一个类选择对话框,竟然看到了它默认显示的“DefaultReverseEngineeringStrategy”类了,我在hibernatetools的安装目录找来找去,终于在plugins\org.hibernate.eclipse_3.2.0.beta6\lib\tools下的hibernate-tools.jar中找到了这个类的影子,用反编译工具反编译一下(懒得去网上下源码了,呵呵)。一个个方法名展现在我面前:
tableToClassName
columnToPropertyName
columnToHibernateTypeName
。。。
    这不就是在把数据库相应的项映射成java相应的项吗?
    开工!
    新建一个类CowNewReverseEngineeringStrategy,继承自DefaultReverseEngineeringStrategy,override  tableToClassName、
columnToPropertyName这两个方法,在这两个方法中写入自己的转换逻辑。
然后打包成jar包,放到plugins\org.hibernate.eclipse_3.2.0.beta6\lib\tools下,然后在plugins\org.hibernate.eclipse_3.2.0.beta6\lib\tools\MANIFEST.MF中把这个新增包的内容加上,关闭eclipse,加个-clean参数启动eclipse,然后点击“Hibernate Code Generation”,把“reveng Strategy”填成“com.cownew.DevTools.hibtools.RevEng.CowNewReverseEngineeringStrategy”,“Run”!!!
晕倒,竟然报错“com.cownew.DevTools.hibtools.RevEng.CowNewReverseEngineeringStrategy
Exception while generating code
Reason   org.hibernate.console.HibernateConsoleRunTimeException:Could not create or find com.   with one argument deleate constructor”

看来是反射调用的时候出了问题,重新打开hibernate-tools.jar,仔细观察,竟然发现了一个DelegatingReverseEngineeringStrategy,它多    了一个参数为“ReverseEngineeringStrategy delegate”的构造函数,而其他调用都是转发给ReverseEngineeringStrategy了,晕倒,搞不懂它在做什么,也没时间研究了,给CowNewReverseEngineeringStrategy也曾街一个参数为“ReverseEngineeringStrategy delegate”的构造函数,重新打包,重新启动eclipse,哈哈,一切搞定,终于生成我可爱的,
public class PersonInfo

  public String getNumber()。。。
  public String getId()。。。

了。
    附全部代码:

package com.cownew.DevTools.hibtools.RevEng;

import java.beans.Introspector;

import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringSettings;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategyUtil;
import org.hibernate.cfg.reveng.TableIdentifier;
import org.hibernate.util.StringHelper;

public class CowNewReverseEngineeringStrategy extends
DefaultReverseEngineeringStrategy
{

 public CowNewReverseEngineeringStrategy(ReverseEngineeringStrategy delegate)
 {  
  super();
 }

 private ReverseEngineeringSettings settings = new ReverseEngineeringSettings();

 public String tableToClassName(TableIdentifier table)
 {
  String tableName = table.getName();
  if (tableName != null && tableName.toUpperCase().startsWith("T_"))
  {
   String pkgName = settings.getDefaultPackageName();
   int lastIndex = tableName.lastIndexOf('_');
   tableName = tableName.substring(lastIndex + 1, tableName.length())
     + "Info";

   String className = toUpperCamelCase(tableName);

   if (pkgName.length() > 0)
    return StringHelper.qualify(pkgName, className);
   return className;

  } else
  {
   return super.tableToClassName(table);
  }
 };

 public String columnToPropertyName(TableIdentifier table, String column)
 {
  if (column != null && column.toUpperCase().startsWith("F"))
  {
   String cownewColName = column.substring(1, column.length());
   
   String decapitalize = Introspector
     .decapitalize(toUpperCamelCase(cownewColName));
   return keywordCheck(decapitalize);
  } else
  {
   return super.columnToPropertyName(table, column);
  }
 }

 private String keywordCheck(String possibleKeyword)
 {
  if (ReverseEngineeringStrategyUtil
    .isReservedJavaKeyword(possibleKeyword))
   possibleKeyword += "_";
  return possibleKeyword;
 }

 public void setSettings(ReverseEngineeringSettings settings)
 {
  super.setSettings(settings);
  this.settings = settings;
 }

 public static void main(String[] args)
 {
  TableIdentifier table = new TableIdentifier("T_BD_Person");
  //TableIdentifier table = new TableIdentifier("T_Person");
  //TableIdentifier table = new TableIdentifier("Person");
  CowNewReverseEngineeringStrategy revEng = new CowNewReverseEngineeringStrategy(null);
  String className = revEng.tableToClassName(table);
  System.out.println(className);
  System.out.println(revEng.columnToPropertyName(table, "FId"));
  System.out.println(revEng.columnToPropertyName(table, "Id"));
 }
}


 

posted @ 2006-07-16 22:27 CowNew开源团队 阅读(1517) | 评论 (4)编辑 收藏

CowNew开源团队网站 http://www.cownew.com
作者是CowNew开源团队发起人之一,邮箱about521  at 163 dot com
论坛 http://www.cownew.com/newpeng/
转载请注明此版权信息


java做的系统给人的印象是什么?占内存!说道这句话就会有N多人站出来为java辩护,并举出一堆的性能测试报告来证明这一点。其实从理论上来讲java做的系统并不比其他语言开发出来的系统更占用内存,那么为什么却有这么N多理由来证明它确实占内存呢???两个字,陋习。
(1)别用new Boolean()。
在很多场景中Boolean类型是必须的,比如JDBC中boolean类型的set与get都是通过Boolean封装传递的,大部分ORM也是用Boolean来封装boolean类型的,比如:
ps.setBoolean("isClosed",new Boolean(true));
ps.setBoolean("isClosed",new Boolean(isClosed));
ps.setBoolean("isClosed",new Boolean(i==3));

通常这些系统中构造的Boolean实例的个数是相当多的,所以系统中充满了大量Boolean实例小对象,这是相当消耗内存的。
Boolean类实际上只要两个实例就够了,一个true的实例,一个false的实例。
Boolean类提供两了个静态变量:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
需要的时候只要取这两个变量就可以了,
比如:
ps.setBoolean("isClosed",Boolean.TRUE);

那么象2、3句那样要根据一个boolean变量来创建一个Boolean怎么办呢?可以使用Boolean提供的静态方法:   Boolean.valueOf()
比如:
 
ps.setBoolean("isClosed",Boolean.valueOf(isClosed));
ps.setBoolean("isClosed",Boolean.valueOf(i==3));
因为valueOf的内部实现是:
return (b ? TRUE : FALSE);
所以可以节省大量内存。

相信如果Java规范直接把Boolean的构造函数规定成private,就再也不会出现这种情况了。
(2)别用new Integer。
和Boolean类似,java开发中使用Integer封装int的场合也非常多,并且通常用int表示的数值通常都非常小。
SUN SDK中对Integer的实例化进行了优化,Integer类缓存了-128到127这256个状态的Integer,如果使用Integer.valueOf(int i),传入的int范围正好在此内,就返回静态实例。
这样如果我们使用Integer.valueOf代替new Integer的话也将大大降低内存的占用。如果您的系统要在不同的SDK(比如IBM SDK)中使用的话,那么可以自己做了工具类封装一下,比如IntegerUtils.valueOf(),这样就可以在任何SDK中都可以使用这种特性。

(3)用StringBuffer代替字符串相加。这个我就不多讲了,因为已经被人讲过N次了。我只想将一个不是笑话的笑话,我在看国内某“著名”java开发的WEB系统的源码中,竟然发现其中大量的使用字符串相加,一个拼装SQL语句的方法中竟然最多构造了将近100个string实例。无语中!
(4)过滥使用哈希表,有一定开发经验的开发人员经常会使用hash表(hash表在JDK中的一个实现就是HashMap)来缓存一些数据,从而提高系统的运行速度。比如使用HashMap缓存一些物料信息、人员信息等基础资料,这在提高系统速度的同时也加大了系统的内存占用,特别是当缓存的资料比较多的时候。其实我们可以使用操作系统中的缓存的概念来解决这个问题,也就是给被缓存的分配一个一定大小的缓存容器,按照一定的算法淘汰不需要继续缓存的对象,这样一方面会因为进行了对象缓存而提高了系统的运行效率,同时由于缓存容器不是无限制扩大,从而也减少了系统的内存占用。现在有很多开源的缓存实现项目,比如ehcache、oscache等,这些项目都实现了FIFO、MRU等常见的缓存算法。
(5)避免过深的类层次结构和过深的方法调用。因为这两者都是非常占用内存的(特别是方法调用更是堆栈空间的消耗大户)。

(6)变量只有在用到它的时候才定义和实例化。
(7)尽量避免使用static变量,类内私有常量可以用final来代替。

posted @ 2006-07-14 23:50 CowNew开源团队 阅读(1274) | 评论 (3)编辑 收藏

        很多关心CowNew的朋友纷纷给我发email或者qq留言,说看到最近CowNew开源项目没有动静了,问我是不是虎头蛇尾死掉了。谢谢大家的关心,CowNew没有停止进步的步伐,最近一段时间没有动静是因为我们在闷头做产品的开发。经过一个多月的努力,在kingchou、紫龙等队友的团结奋斗下,SQL解析引擎和JDBMonitor都已经取得了阶段性的成果。
        SQL解析引擎已经可以生成完整的异构SQLAST,除有少数小bug之外已经基本达到了预期的目标。另外在SQL解析引擎基础上开发的CowNewSQL翻译器也可以实现了基本的功能。可以翻译大部分主流的sql语句,比如:
(1)可以将符合CowNewSQL语法的select now()翻译成对应如下的特定平台sql:
mssql:Select GETDATE()
mysql:Select NOW()
oracle8i:Select SYSDATE FROM DUAL
oracle9i:Select SYSDATE FROM DUAL
(2)可以将符合CowNewSQL语法的
update T2 set fid=t1.fid from (select * from t2
left join t3 on t3.fid=t2.fid union select * from t5)
翻译成对应如下的特定平台sql:
mssql:UPDATE T2 SET fid = t1.fid
FROM(
Select *
From t2 left join t3 on t3.fid = t2.fid
union Select *
From t5
)
mysql:UPDATE T2 SET fid = t1.fid
FROM(
Select *
From t2 left join t3 on t3.fid = t2.fid
union Select *
From t5
)
oracle8i:UPDATE T2 SET fid = t1.fid
FROM(
Select *
From t2,t3 WHERE t3.fid = t2.fid(+)
union Select *
From t5
)
oracle9i:UPDATE T2 SET fid = t1.fid
FROM(
Select *
From t2 left join t3 on t3.fid = t2.fid
union Select *
From t5
)

(2)可以将符合CowNewSQL语法的
select top 20 ABS(-1),lcase(trim(name)),tochar(now()), ADD_SECONDS(now(),22),t2.name,DateAdd(Year,now(),3) from T_Table
,(select * from T_MD where FID=2222222222) as tmd
left join T_T4 on tmd.id>T_Table.id
left join T_T2 as t2 on T_T2.id=T_Table.id
right join T_T3 as t3 on t2.id=t3.id
翻译成对应如下的特定平台sql:
mssql:Select  top 20
 ABS(-1) , LOWER(LTRIM(RTRIM(name)) ,CONVERT(VARCHAR, GETDATE()),DATEADD(second,GETDATE(),22),t2.name,DATEADD(Year, GETDATE(), 3)
From T_Table,
Select *
From T_MD
Where FID = 2222222222 as tmd
 left join T_T4 on tmd.id > T_Table.id left join T_T2 as t2 on T_T2.id = T_Table.id right join T_T3 as t3 on t2.id = t3.id
mysql:Select  ABS(-1) , LOWER(LTRIM(RTRIM(name)) ,CONCAT('', NOW()),DATE_ADD(NOW(), INTERVAL 22 SECOND),t2.name,DATE_ADD(3, INTERVAL NOW() YEAR)
From T_Table,
Select *
From T_MD
Where FID = 2222222222 as tmd
 left join T_T4 on tmd.id > T_Table.id left join T_T2 as t2 on T_T2.id = T_Table.id right join T_T3 as t3 on t2.id = t3.id limit 0, 20

oracle8i:Select  ABS(-1) , LOWER(LTRIM(RTRIM(name)) , TO_CHAR(SYSDATE) ,(SYSDATE + 22/86400),t2.name,add_months(3, TRUNC(SYSDATE) * 12)
From T_Table,
Select *
From T_MD
Where FID = 2222222222 as tmd
,T_T4,T_T2 as t2,T_T3 as t3 WHERE ROWNUM <= 20
 AND tmd.id > T_Table.id(+) AND T_T2.id = T_Table.id(+) AND t2.id(+) = t3.id
oracle9i:Select  ABS(-1) , LOWER(LTRIM(RTRIM(name)) , TO_CHAR(SYSDATE) ,(SYSDATE + 22/86400),t2.name,add_months(3, TRUNC(SYSDATE) * 12)
From T_Table,
Select *
From T_MD
Where FID = 2222222222 as tmd
 left join T_T4 on tmd.id > T_Table.id left join T_T2 as t2 on T_T2.id = T_Table.id right join T_T3 as t3 on t2.id = t3.id WHERE ROWNUM <= 20

        但是这些sql翻译只是按照语法手册进行的翻译,还没有经过正式数据库环境的测试,还需要进一步的测试。
        目前仅支持MSSQLSERVER,MYSQL,Oracle8i,Oracle9i,我们计划进一步支持DB2UDB,FireBird、ACCESS等数据库。而且SQL解析引擎是用JDK5开发的,我们将是用Retrotranslator将其转换个以保证可以在JDK1.4上运行。

        JDBMonitor的需求已经基本完成,但是新增的功能目前只能运行在MSSQLSERVER上,我们准备等COWNEWSQL翻译器开发完毕后,将JDBMonitor涉及到数据库操作的地方是用COWNEWSQL翻译器来完成多数据库支持,所以我们将会推迟JDBMonitor的原计划的发版日期。
        目前我们的项目还是很缺乏高手,比如CowNewSQL这块就缺乏对各种数据库比较熟悉的朋友,还有能对CowNewSQL进行全面测试的朋友,希望对这方面开发比较感兴趣的能加入到我们的开发中来,共同打造优秀的开源产品。可以直接给我发送邮件about521 at 163.com

posted @ 2006-07-03 00:35 CowNew开源团队 阅读(2716) | 评论 (0)编辑 收藏

以下内容转自韩寒的“太变态了!”
"
 
... ...
今年的超级女声开始了,
加油好男儿也开始了,
但是我发现,
就我看的这些选手里,
明显有点问题,
仿佛两个节目弄反了,
男的全是能挤出奶来的,
还经常对着镜头耶耶耶耶的,
耶他大爷..
女的全是弄成男人样还压低嗓子说话的.
总之就是,
让异性看着都一点性欲没有.
太变态了.
太变态了.
我相信超级女声里很多是赶时髦,
可能性格并不如此,
但那些男的,
我真恨不得冲上去对着他们的裤裆就是一脚... ..."
posted @ 2006-06-23 18:40 CowNew开源团队 阅读(343) | 评论 (1)编辑 收藏

CowNew开源团队网站 http://www.cownew.com
作者 杨中科 是CowNew开源团队JDBMonitor开发组的开发人员,邮箱about521  at 163 dot com
论坛 http://www.cownew.com/newpeng/
转载请注明此版权信息
以前我一直是用使用数据源的系统测试JDBMonitor,昨天我准备把JDBMonitor嵌入到一个小的jsp留言板中,这个留言板写的非常简单,数据库操作也是connection随取随用、用完了就关这种最简单的形式,这倒是帮助我发现了一个超级大bug。
在记事本运行中常常不规律的DataBaseDBListener的logSQL方法报空指针错误,是在logStatement.setString(1, randomGUID.toString());这一句抛出的,我跟踪到mysql驱动的内部(我使用的是mysql数据库做DataBaseDBListener的输出数据库),发现在setString的实现中会去调用connection的方法,而此时connection已经是null了,所以会报空指针错误。
从其不规律的特点我判断出应该是多线程导致的问题。我跟踪发现,有的时候是先调用DataBaseDBListener的close后logSql才被调用。经过分析找出了问题所在,问题就在DBLogger中内部类LogConsumer的startConsumer方法,这个是修改以前的代码:
for (;;)
 {
  SQLInfo info = (SQLInfo) channel.take();    

  if(info==null)
  {
   ontinue;
  }
  for (int i = 0, n = dbListeners.length; i < n; i++)
  {
   dbListeners[i].logSql(info);
  }

 }


在调用channel.take()以后,这个SQLInfo就从channel中去除了。这时如果DBLogger的方法被调用,那么即使dbListeners[i].logSql(info)仍然在运行,但是DBLogger会认为channel已经空了,所有的dbListeners都可以被close了,而在DataBaseDBListener的close方法中会把输出目标数据库connection关掉,那么此时如果DataBaseDBListener的logSql方法还在调用的话,那么一旦使用这个connection,那么就会出现错误了。
我是如下修改的:
修改BlockedChannel类,去掉其take方法,增加一个peek方法和一个remove方法,peek方法是从channel中查出一个对象,但是不把它从channel中移走,只有调用remove方法后才会被移走。
修改DBLogger中内部类LogConsumer的startConsumer方法为如下:
for (;;)
 {
  SQLInfo info = (SQLInfo) channel.peek();
  if(info==null)
  {
   continue;
  }
  for (int i = 0, n = dbListeners.length; i < n; i++)
  {
   dbListeners[i].logSql(info);
  }
  channel.remove(info);
 }

也就是只有SQLInfo被处理完了,才会从channel中移走。
看来JDBMonitor还是要多多测试多多验证,我近期准备对JDBMonitor进行性能测试,看看有没有并发问题有没有性能问题,不要再急着加新功能了,把这些基础的功能做好再说,否则别人用着用着就出现中断性错误了,那将会是比缺少功能更可怕的事情。一位同事曾经说过一句话:“做的越多错的越多。不要你做的多好,只要把已经做完的东西做的更好就可以了。”,看来确实有一定道理呀。把基本的东西做好再说,否则被人骂不专业就惨了。

posted @ 2006-06-15 22:52 CowNew开源团队 阅读(830) | 评论 (0)编辑 收藏

CowNew开源团队网站 http://www.cownew.com
论坛 http://www.cownew.com/newpeng/
转载请注明此版权信息

今天做的事情比较杂,所以感想也比较杂:
1、java程序的远程调试。
“JPDA是sun jdk自带的远程调试机制。它提供了一套标准的调试接口,可以从虚拟机一级允许外界用特定协议探测虚拟机内部的运作细节。只要你装了jdk 1.2以上的sun jdk,就已经有了jpda支持。 只要是用标准JDK中java.exe运行的应用,就可以用jpda进行远程调试。以web应用的开发为例,servlet和ejb的调试一直不是一件太容易的事情。虽然jbuilder、eclipse等有一些常见的应用服务器,如tomcat, weblogic 6.x,的调试插件,但是用法各不相同,而且很容易由于版本问题导致出现各种问题,而且对于有的服务器则没有相应的IDE插件。
JPDA就不一样。由于它是java平台的标准功能之一,所以我们其实可以调试任何用jdk运行的程序。只需要做两件事:
(1)、 在被调试的应用上,增加几个java虚拟机启动参数,让它启动后进入调试服务器模式;
(2) 在本机或网络中另一台机器上用某种jpda客户端程序,attach到被调试的应用程序(可以通过socket或共享内存两种方式)。jpda本身只是一个接口,调试工具的好用与否就要看其对jpda的应用如何。jdb是sun jdk自带的命令行jpda调试客户程序,你可以用命令行设置断点,查看变量值,等等。但不是很直观。而jbuilder、eclipse的jpda调试器就做到了将jpda图形化,可以直观的设置断点,跟踪程序,查看量值,等等。 ”---本段改编自“http://www.cjsdn.com/post/print?bid=7&id=1376”

以elipse+tomcat为例:
(1)打开Tomcat 5.0\bin下的catalina.bat,在“set JPDA= ”下加入如下两行:
set JPDA_TRANSPORT=dt_socket
set JPDA_ADDRESS=8787
(2)启动tomcat
(3)在eclipse的debug中新建一个“Remote Java Application”,工程选择被调试的远程程序的源码工程,host填127.0.0.1,port为8787
(4)运行调试。
这样我们就可以在eclipse中下断点调试tomcat中运行的程序了。让那些乱七八糟的插件哪凉快去哪呆着吧。
注意一定要保证eclipse工程中的源码和tomcat中运行的程序一致。

2、调用对象的wait方法的时候有可能会抛出InterruptedException异常,以前我是把这个异常再次抛出,今天运行发现当这个异常抛出的时候,线程就死掉了。因此不能简单的将此异常re-throw,必须处理它,比如JDBMonitor中的BlockedChannel的take方法就要如下改写:
public synchronized Object take()
 {
  if (container.isEmpty())
  {
   try
   {
    wait();
   } catch (InterruptedException e)
   {
    return null;
   }
  }
  Object obj = container.pop();
  return obj;
 }

3、windows下运行linux的最好的工具
最近一直想验证JDBMonitor在linux底下是否有bug,但是听人说过,linux安装不当很容易发生数据丢失,因此一直不敢装。而用virtual PC,VMWare之类的软件又太消耗内存,而且需要虚拟机安装完成再安装linux。今天无意中搜索到一个windows下的linux虚拟机:MetroPipe VPM 。
下载地址:
http://www.metropipe.net/ProductsPVPMDownload.shtml
解压后直接运行其中的qemu-win.bat就能启动Linux。不用安装,启动关闭都非常快,而且占用内存相对来说比较小。
唯一一个缺点就是默认就进入图形模式,抽时间看看怎么配置让它启动以后进入字符模式。
详细可以参考:http://www.highand.com/viewthread.php?tid=545

 

posted @ 2006-06-13 01:06 CowNew开源团队 阅读(962) | 评论 (0)编辑 收藏

对于一个新手来说,安装Linux势必会带来很大的风险。胆子小的最后决定继续享受Windows,胆子大的有一些不幸地丢失了硬盘中的所有数据。现在你不必提心吊胆了!在Windows下你可以轻易运行Linux,无需安装,你只要下载一个MetroPipe VPM(以下简称VPM),解压后运行一下就OK了。

QUOTE:

MetroPipe VPM 小档案

软件版本:不详 软件大小:83MB
软件性质:免费 适用平台:Windows/Linux
下载地址:http://www.metropipe.net/ProductsPVPMDownload.shtml
软件备注:在下载页面中包含了多种下载方式,建议使用“Download.zip file via HTTP”右侧的Download按钮下载。


VPM其实是一个多平台的小型虚拟机软件,这个压缩包中包含了一个完整的Linux版本。解压后直接运行其中的qemu-win.bat就能启动Linux(如果硬盘配置较低,启动时间会比较长),根据弹出窗口的提示回车登录Linux,出现桌面后就能和普通Linux一样cao作了。磁盘目录结构、命令等都和普通的Linux完全相同,如果想练手的话非常合适。


*为什么鼠标逃不出Linux窗口了

进入Linux之后,你会发现鼠标无法脱离Linux窗口了,要再次回到Windows,可以使用组合键“Ctrl+Shift”。


*能否全屏显示

使用组合键“Ctrl+Shift+F"(要回到窗口模式只需再按一次)就能全屏cao作Linux,但是全屏之后 屏闪比较严重,还是窗口模式比较对得起自己的眼睛。

*在这个Linux中能否上网

运行后直接映射Windows中当前存在的网络连接,无需手动配置。可以用Linux中自带的FireFox看网页、Thunderbird收邮件、axFTP上传文件,但可惜只支持英语

*小提示
要关闭时可以直接关闭窗口,也可以右键点击桌面空白处选择“Power Down→Shutdown”。


摘自《电脑爱好者》2006年第5期 Page 40

posted @ 2006-06-12 23:59 CowNew开源团队 阅读(1606) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 上一页 19 20 21 22 23 24 25 26 27 下一页 Last