JDKJREJVM区别

Posted on

JDKJREJVM区别

JDK,JRE,JVM区别与联系

文章分类**:Java编程**

很多朋友可能跟我一样,已经使用JAVA开发很久了,可是对JDK,JRE,JVM这三者的联系与区别,一直都是模模糊糊的。

今天特写此文,来整理下三者的关系。



JDK : Java Development ToolKit(Java开发工具包)。JDK是整个JAVA的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。

最主流的JDK是Sun公司发布的JDK,除了Sun之外,还有很多公司和组织都开发了属于自己的JDK,例如国外IBM公司开发了属于自己的JDK,国内淘宝也开发了属于自己的JDK,各个组织开发自己的JDK都是为了在某些方面得到一些提高,以适应自己的需求,比如IBM的JDK据说运行效率就比SUN的JDK高的多。但不管怎么说,我们还是需要先把基础的Sun JDK掌握好。

JDK有以下三种版本:

J2SE,standard edition,标准版,是我们通常用的一个版本J2EE,enterpsise edtion,企业版,使用这种JDK开发J2EE应用程序J2ME,micro edtion,主要用于移动设备、嵌入式设备上的java应用程序

我们常常用JDK来代指Java API,Java API是Java的应用程序接口,其实就是前辈们写好的一些java Class,包括一些重要的语言结构以及基本图形,网络和文件I/O等等 ,我们在自己的程序中,调用前辈们写好的这些Class,来作为我们自己开发的一个基础。当然,现在已经有越来越多的性能更好或者功能更强大的第三方类库供我们使用。



JRE:Java  Runtime  Enviromental(java运行时环境)。也就是我们说的JAVA平台,所有的Java程序都要在JRE下才能运行。包括JVM和JAVA核心类库和支持文件。与JDK相比,它不包含开发工具——编译器、调试器和其它工具。



JVM:Java Virtual Mechinal(JAVA虚拟机)。JVM是JRE的一部分,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 的主要工作是解释自己的指令集(即字节码)并映射到本地的 CPU 的指令集或 OS 的系统调用。Java语言是跨平台运行的,其实就是不同的操作系统,使用不同的JVM映射规则,让其与操作系统无关,完成了跨平台性。JVM 对上层的Java 源文件是不关心的,它关注的只是由源文件生成的类文件( class file )。类文件的组成包括JVM 指令集,符号表以及一些补助信息。

下图很好的表面了JDK,JRE,JVM三者间的关系:

http://dl.iteye.com/upload/attachment/364841/7dbc84af-e878-3718-beb5-6471ad99b995.gif

我们开发的实际情况是:我们利用JDK(调用JAVA API)开发了属于我们自己的JAVA程序后,通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,在JRE上运行这些JAVA字节码,JVM解析这些字节码,映射到CPU指令集或OS的系统调用。

url: http://java-mzd.iteye.com/blog/838514

Java Annotation详解

Posted on

Java Annotation详解

元数据的作用

如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:

l 编写文档:通过代码里标识的元数据生成文档。

l 代码分析:通过代码里标识的元数据对代码进行分析。

l 编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。

基本内置注释

**@Override** 注释能实现编译时检查,你可以为你的方法添加该注释,以声明该方法是用于覆盖父类中的方法。如果该方法不是覆盖父类的方法,将会在编译时报错。例如我们为某类重写toString() 方法却写成了tostring() ,并且我们为该方法添加了@Override 注释;

 **@Deprecated** 的作用是对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc 里的 @deprecated 标记有相同的功能,准确的说,它还不如javadoc @deprecated ,因为它不支持参数,

注意:要了解详细信息,请使用 -Xlint:deprecation 重新编译。

**@SuppressWarnings** 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了,参数如下:

deprecation 使用了过时的类或方法时的警告

unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型

fallthrough 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告

path 在类路径、源文件路径等中有不存在的路径时的警告

serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告

finally 任何 finally 子句不能正常完成时的警告

all 关于以上所有情况的警告

注意:要了解详细信息,请使用 -Xlint:unchecked 重新编译。


定制注释类型

好的,让我们创建一个自己的注释类型(annotation type )吧。它类似于新创建一个接口类文件,但为了区分,我们需要将它声明为@interface, 如下例:

public @interface NewAnnotation {

}

使用定制的注释类型

我们已经成功地创建好一个注释类型NewAnnotation ,现在让我们来尝试使用它吧,如果你还记得本文的第一部分,那你应该知道他是一个标记注释,使用也很容易,如下例:

public class AnnotationTest {

@NewAnnotation

public static void main(String[] args) {



}

}

添加变量

J2SE 5.0 里,我们了解到内置注释@SuppressWarnings() 是可以使用参数的,那么自定义注释能不能定义参数个数和类型呢?答案是当然可以,但参数类型只允许为基本类型、String 、Class 、枚举类型等,并且参数不能为空。我们来扩展NewAnnotation ,为之添加一个String 类型的参数,示例代码如下:

public @interface NewAnnotation {

String value();

}

使用该注释的代码如下:正如你所看到的,该注释的使用有两种写法,这也是在之前的文章里所提到过的。如果你忘了这是怎么回事,那就再去翻翻吧。

public class AnnotationTest {

@NewAnnotation("Just a Test.")

public static void main(String[] args) {

    sayHello();

}



@NewAnnotation(value="Hello NUMEN.")

public static void sayHello() {

    // do something

}

}

为变量赋默认值

我们对Java 自定义注释的了解正在不断的增多,不过我们还需要更过,在该条目里我们将了解到如何为变量设置默认值,我们再对NewAnnotaion 进行修改,看看它会变成什么样子,不仅参数多了几个,连类名也变了。但还是很容易理解的,我们先定义一个枚举类型,然后将参数设置为该枚举类型,并赋予默认值。

public @interface Greeting {

public enum FontColor {RED, GREEN, BLUE};



String name();



String content();



FontColor fontColor() default FontColor.BLUE;

}

限定注释使用范围

当我们的自定义注释不断的增多也比较复杂时,就会导致有些开发人员使用错误,主要表现在不该使用该注释的地方使用。为此,Java 提供了一个ElementType 枚举类型来控制每个注释的使用范围,比如说某些注释只能用于普通方法,而不能用于构造函数等。下面是Java 定义的ElementType 枚举:

package java.lang.annotation;

public enum ElementType {

TYPE, // Class, interface, or enum (but not annotation)

FIELD, // Field (including enumerated values)

METHOD, // Method (does not include constructors)

PARAMETER, // Method parameter

CONSTRUCTOR, // Constructor

LOCAL_VARIABLE, // Local variable or catch clause

ANNOTATION_TYPE, // Annotation Types (meta-annotations)

PACKAGE // Java package

}

下面我们来修改Greeting 注释,为之添加限定范围的语句,这里我们称它为目标(Target )使用方法也很简单,如下:

@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

public @interface Greeting {

}

正如上面代码所展示的,我们只允许Greeting 注释标注在普通方法和构造函数上,使用在包申明、类名等时,会提示错误信息。

注释保持性策略

public enum RetentionPolicy {

SOURCE,// Annotation is discarded by the compiler

CLASS,// Annotation is stored in the class file, but ignored by the VM

RUNTIME// Annotation is stored in the class file and read by the VM

}

RetentionPolicy 的使用方法与ElementType 类似,简单代码示例如下:

@Retention(RetentionPolicy.RUNTIME)

@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

文档化功能

Java 提供的Documented 元注释跟Javadoc 的作用是差不多的,其实它存在的好处是开发人员可以定制Javadoc 不支持的文档属性,并在开发中应用。它的使用跟前两个也是一样的,简单代码示例如下:

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

public @interface Greeting {

}

值得大家注意的是,如果你要使用@Documented 元注释,你就得为该注释设置RetentionPolicy.RUNTIME 保持性策略。为什么这样做,应该比较容易理解,这里就不提了。

**

标注继承

继承应该是Java 提供的最复杂的一个元注释了,它的作用是控制注释是否会影响到子类,简单代码示例如下:

@Inherited

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })

public @interface Greeting {

}

读取注释信息

当我们想读取某个注释信息时,我们是在运行时通过反射来实现的,如果你对元注释还有点印象,那你应该记得我们需要将保持性策略设置为RUNTIME ,也就是说只有注释标记了@Retention(RetentionPolicy.RUNTIME)的,我们才能通过反射来获得相关信息,下面的例子我们将沿用前面几篇文章中出现的代码,并实现读取AnnotationTest 类所有方法标记的注释并打印到控制台。好了,我们来看看是如何实现的吧:

public class AnnotationIntro {

public static void main(String[] args) throws Exception {

Method[] methods = Class.forName(

"com.gelc.annotation.demo.customize.AnnotationTest")

.getDeclaredMethods();

Annotation[] annotations;

for (Method method : methods) {

annotations = method.getAnnotations();

for (Annotation annotation : annotations) {

System.out.println(method.getName() + " : "

+ annotation.annotationType().getName());

}

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

Annotation(注解)

Annotation对于程序运行没有影响,它的目的在于对编译器或分析工具说明程序的某些信息,您可以 在包,类,方法,域成员等加上Annotation.每一个Annotation对应于一个实际的Annotation类型.

1 限定Override父类方法@Override java.lang.Override是J2SE5.0中标准的Annotation类型之一,它对编译器说明某个方法必须 是重写父类中的方法.编译器得知这项信息后,在编译程序时如果发现被@Override标示的方法 并非重写父类中的方法,就会报告错误. 例,如果在定义新类时想要重写Object类的toString()方法,可能会写成这样: public class CustomClass{ public String ToString(){ return "customObject"; } } 在编写toString()方法时,因为输入错误或其他的疏忽,将之写成ToString()了,编译这个类时 并不会出现任何的错误,编译器不会知道您是想重写toString()方法,只会以为是定义了一个新 的ToString()方法. 可以使用java.lang.Override这个Annotation类型,在方法上加一个@Override的Annotation 这可以告诉编译器现在定义的这个方法,必须是重写父类中的同包方法. public class CustomClass{ @Override public String toString(){ return "coustomObject"; } } java.lang.Override是一个Marker Annotation,简单地说就是用于标示的Annotation,Annotation 名称本身表示了要给工具程序的信息。

Annotation类型与Annotation实际上是有区分的,Annotation是Annotation类型的实例,例如 @Override是个Annotation,它是java.lang.Override类型的一个实例,一个文件中可以有很多 个@Override,但它们都是属于java.lang.Override类型。

2 标示方法为Deprecated @Deprecated java.lang.Deprecated也是J2SE5.0中标准的Annotation类型之一。它对编译器说明某个方法已经不 建议使用。如果有开发人员试图使用或重写被@Deprecated标示的方法,编译器必须提出警告信息。 例: public class Something{ @Deprecated public Something getSomething(){ return new Something(); } } 如果有人试图在继承这个类后重写getSomething()方法,或是在程序中调用getSomething()方法, 则编译时会有警告出现。 java.lang.Deprecated也是一个Marker Annotation简单地说就是用于标示。

3 抑制编译器警告 @SuppressWarnings java.lang.SuppressWarnings也是J2SE5.0中标准的Annotation类型之一,它对编译器说明某个方法 中若有警告信息,则加以抑制,不用在编译完成后出现警告。 例: public class SomeClass2{ @SuppressWarnings(value={"unchecked"}); public void doSomething(){ Map map = new HashMap(); map.put("some","thing"); } } 这样,编译器将忽略unchecked的警告,您也可以指定忽略多个警告: @SuppressWarnings(value={"unchecked","deprecation"}); @SuppressWarnings是所谓的Single-Value Annotation,因为这样的Annotation只有一个成员,称为 value成员,可在使用Annotation时作额外的信息指定。

自定义Annotation类型 可以自定义Annotation类型,并使用这些自定义的Annotation类型在程序代码中使用Annotation,这些 Annotation将提供信息给程序代码分析工具。 首先来看看如何定义Marker Annotation,也就是Annotation名称本身即提供信息。对于程序分析工具来 说,主要是检查是否有Marker Annotation的出现,并做出对应的动作。要定义一个Annotation所需的动作 ,就类似于定义一个接口,只不过使用的是@interface。 例: public @interface Debug{}

由于是一个Marker Annotation,所以没有任何成员在Annotation定义中。编译完成后,就可以在程序代码 中使用这个Annotation。 public class SomeObject{ @Debug public void doSomething(){ ...... } } 稍后可以看到如何在Java程序中取得Annotation信息(因为要使用Java程序取得信息,所以还要设置 meta-annotation,稍后会谈到)

接着来看看如何定义一个Single-Value Annotation,它只有一个Value成员。 例: public @interface UnitTest{ String value(); } 实际上定义了value()方法,编译器在编译时会自动产生一个value的域成员,接着在使用UnitTest Annotation时要指定值。如: public class MathTool{ @UnitTest("GCD") public static int gcdOf(int num1,int num2){ ............... } } @UnitTest("GCD")实际上是@UnitTest(value="GCD")的简便写法,value也可以是数组值。如: public @interface FunctionTest{ String[] value(); } 在使用时,可以写成@FunctionTest({"method1","method2"})这样的简便形式。或是 @FunctionTest(value={"method1","method2"})这样的详细形式.

也可以对value成员设置默认值,使用default关键词即可。 例: public @interface UnitTest2{ String value() default "noMethod"; } 这样如果使用@UnitTest2时没有指定value值,则value默认就是noMethod.

也可以为Annotation定义额外的成员,以提供额外的信息给分析工具,如: public @interface Process{ public enum Current{NONE,REQUIRE,ANALYSIS,DESIGN,SYSTEM}; Current current() default Current.NONE; String tester(); boolean ok(); } 运用: public class Application{ @process( current = Process.Current.ANALYSIS, tester = "Justin Lin", ok = true ) public void doSomething(){ ........... } } 当使用@interface自行定义Annotation类型时,实际上是自动继承了 java.lang.annotation接口,并由编译器自动完成其他产生的细节,并且在定义Annotation类型时, 不能继承其他的Annotation类型或接口. 定义Annotation类型时也可以使用包机制来管理类。由于范例所设置的包都是onlyfun.caterpillar, 所以可以直接使用Annotation类型名称而不指定包名,但如果是在别的包下使用这些自定义的Annotation ,记得使用import告诉编译器类型的包们置。 如: import onlyfun.caterpillar.Debug; public class Test{ @Debug public void doTest(){ ...... } } 或是使用完整的Annotation名称.如: public class Test{ @onlyfun.caterpillar.Debug public void doTest(){ ...... } }

meta-annotation 所谓neta-annotation就是Annotation类型的数据,也就是Annotation类型的Annotation。在定义 Annotation类型时,为Annotation类型加上Annotation并不奇怪,这可以为处理Annotation类型 的分析工具提供更多的信息。

1 告知编译器如何处理annotation @Retention java.lang.annotation.Retention类型可以在您定义Annotation类型时,指示编译器该如何对待自定 义的Annotation类型,编译器默认会将Annotation信息留在.class文件中,但不被虚拟机读取,而仅用 于编译器或工具程序运行时提供信息。

在使用Retention类型时,需要提供java.lang.annotation.RetentionPolicy的枚举类型。 RetentionPolicy的定义如下所示: package java.lang.annotation; public enum RetentionPolicy{ SOURCE,//编译器处理完Annotation信息后就没有事了 CLASS,//编译器将Annotation存储于class文件中,默认 RUNTIME //编译器将Annotation存储于class文件中,可由VM读入

}

RetentionPolicy为SOURCE的例子是@SuppressWarnings,这个信息的作用仅在编译时期告知 编译器来抑制警告,所以不必将这个信息存储在.class文件中。

RetentionPolicy为RUNTIME的时机,可以像是您使用Java设计一个程序代码分析工具,您必须让VM能读出 Annotation信息,以便在分析程序时使用,搭配反射机制,就可以达到这个目的。\

J2SE6.0的java.lang.reflect.AnnotatedElement接口中定义有4个方法: public Annotation getAnnotation(Class annotationType) public Annotation[] getAnnotations(); public Annotation[] getDeclaredAnnotations() public boolean isAnnotationPresent(Class annotationType);

Class,Constructor,field,Method,Package等类,都实现了AnnotatedElement接口,所以可以从这些 类的实例上,分别取得标示于其上的Annotation与相关信息。由于在执行时读取Annotation信息,所以定 义Annotation时必须设置RetentionPolicy为RUNTIME,也就是可以在VM中读取Annotation信息。 例: package onlyfun.caterpillar; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPllicy;

@Retention(RetentionPolicy.RUNTIME) public @interface SomeAnnotation{ String value(); String name(); } 由于RetentionPolicy为RUNTIME,编译器在处理SomeAnnotation时,会将Annotation及给定的相关信息 编译至.class文件中,并设置为VM可以读出Annotation信息。接下来: package onlyfun.caterpillar; public class SomeClass3{ @SomeAnotation{ value="annotation value1", name="annotation name1" } public void doSomething(){ ...... } }

现在假设要设计一个源代码分析工具来分析所设计的类,一些分析时所需的信息已经使用Annotation标示于类 中了,可以在执行时读取这些Annotation的相关信息。例:

package onlyfun.caterpillar;

import java.lang.annotation.Annotation; import java.lang.reflect.Method;

public class AnalysisApp{ public static void main(String [] args) throws NoSuchMethodException{ Class c = SomeClass3.class; //因为SomeAnnotation标示于doSomething()方法上 //所以要取得doSomething()方法的Method实例 Method method = c.getMethod("doSomething"); //如果SomeAnnotation存在 if(method.isAnnotationPresent(SomeAnnotation.class){ System.out.println("找到@SomeAnnotation"); //取得SomeAnnotation SomeAnnotation annotation = method.getAnnotation(SomeAnnotation.class); //取得vlaue成员值 System.out.println(annotation.value); //取得name成员值 System.out.println(annotation.name()); }else{ System.out.println("找不到@SomeAnnotation"); } //取得doSomething()方法上所有的Annotation Annotation[] annotations = method.getAnnotations(); //显示Annotation名称 for(Annotation annotation : annotations){ System.out.println("Annotation名称:"+annotation.annotationType().getName()); } } } 若Annotation标示于方法上,就要取得方法的Method代表实例,同样的,如果Annotation标示于类或包上, 就要分别取得类的Class代表的实例或是包的Package代表的实例。之后可以使用实例上的getAnnotation() 等相关方法,以测试是否可取得Annotation或进行其他操作。

2 限定annotation使用对象 @Target 在定义Annotation类型时,使用java.lang.annotation.Target可以定义其适用的时机,在定义时要指定 java.lang.annotation.ElementType的枚举值之一。 public enum elementType{ TYPE,//适用class,interface,enum FIELD,//适用于field METHOD,//适用于method PARAMETER,//适用method上之parameter CONSTRUCTOR,//适用constructor LOCAL_VARIABLE,//适用于区域变量 ANNOTATION_TYPE,//适用于annotation类型 PACKAGE,//适用于package }

举例,假设定义Annotation类型时,要限定它只能适用于构造函数与方法成员,则: package onlyfun.caterpillar;

import java.lang.annotation.Target; import java.lang.annotation.ElementType;

@Target({ElementType.CONSTRUCTOR,ElementType.METHOD}) public @interface MethodAnnotation{}

将MethodAnnotation标示于方法之上,如:

public class SomeoneClass{ @onlyfun.caterpillar.MethodAnnotation public void doSomething(){ ...... } }

3 要求为API文件的一部分 @Documented

在制作Java Doc文件时,并不会默认将Annotation的数据加入到文件中.Annnotation用于标示程序代码以便 分析工具使用相关信息,有时Annotation包括了重要的信息,您也许会想要在用户制作Java Doc文件的同时, 也一并将Annotation的信息加入到API文件中。所以在定义Annotation类型时,可以使用 java.lang.annotation.Documented.例:

package onlyfun.caterpillar;

import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;

@Documented @Retention(RetentionPolicy.RUNTIME) public @interface TwoAnnotation{}

使用java.lang.annotation.Documented为定义的Annotation类型加上Annotation时,必须同时使用Retention 来指定编译器将信息加入.class文件,并可以由VM读取,也就是要设置RetentionPolicy为RUNTIME。接着可以使 用这个Annotation,并产生Java Doc文件,这样可以看到文件中包括了@TwoAnnotation的信息.

4 子类是否可以继承父类的annotation @Inherited 在定义Annotation类型并使用于程序代码上后,默认父类中的Annotation并不会被继承到子类中。可以在定义 Annotation类型时加上java.lang.annotation.Inherited类型的Annotation,这让您定义的Annotation类型在 被继承后仍可以保留至子类中。 例: package onlyfun.caterpillar;

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Inherited;

@Retention(RetentionPolicy.RUNTIME) @Inherited public @interface ThreeAnnotation{ String value(); String name(); } 可以在下面的程序中使用@ThreeAnnotation: public class SomeoneClass{ @onlyfun.caterpillar.ThreeAnnotation( value = "unit", name = "debug1" ) public void doSomething(){ ..... } } 如果有一个类继承了SomeoneClass类,则@ThreeAnnotation也会被继承下来。 来源: [http://djjchobits.iteye.com/blog/569000](http://djjchobits.iteye.com/blog/569000)

IOC原理分析

Posted on

IOC原理分析

IOC原理分析

文章分类**:Java编程**

IOC(inversion of control)控制反转

在我们的程序中,要实现某个功能,我们都会用到两个或两个以上的类来协同完成,那么在一个类中,我们就会要有它的合作类的引用,也就是说这个类依赖于别的类,这个合作类的获取,将会有一下几种不同的情况

依赖获取的三种方式:

Java**代码 [收藏代码]()****

  1. 情况1.自己生成

  2. Class person{

  3. Eat(){

  4. Apple a=new Apple();

  5. }

  6. }

第一种方式:在person的eat()方法里就把吃的水果写死,从开始就创建对象,

  缺点 :1.Person类必须依赖于Apple类,如果Apple类没完成,则编译都不能通过

2.不能再更改,当person想再吃别的水果的时候,无法进行修改

3.很难共享给其他人,只能单独使用

4.person类要对Apple的整个生命周期负责,两个类始终耦合在一起

Java**代码 [收藏代码]()****

  1. 情况2 通过中介得到

  2. Class person{

  3. Eat(String name){

  4. Apple a=(Apple)Fruitfactory.getInstance(“name”);

  5. }}

第二种方式:1.通过使用工程类,间接得到需要的对象

通过使用工程类,程序效果确实得到了改进,但是问题依然存在

缺点:1.每个子类的生成的代码都写死在工厂类里面了,如果要换个子类,则必须更改工厂类中的方法

            2.面向接口编程,一般都会使用工厂类,一般每个接口都会对于一个工程类,当项目非常大的时候,则会有非常多的工厂类

Java**代码 [收藏代码]()****

  1. 情况3.直接被注入

  2. Class person{

  3. Eat(Fruit fruit){

  4. //apple为Fruit实现类

  5. }

  6. }

第三种方式:只需要在外部传入一个现成的对象给方法调用,不同的实现传入不同的对象即可(感觉这么说就是简单的面向接口的编程的好处,具体优势,请看后面)

在系统中,我们可以用一个外部的容器Container 来统一调配整个系统的运行,将对象的创建和获取提取到外部容器,由外部容器为每个组件提供需要的组建.

例如:

在容器中创建Fruit类对象apple,

将Person类依赖的Fruit对象传递给Person类

将了这么多,那么,到底是控制的什么被反转了呢?

获得依赖对象的方式被反转了.

也就是说

将一个对象如何获取它所依赖的对象这个任务的控制权反转到外部容器中。对象的依赖都是在对象创建时,由负责协调整个系统中各个实体间关系的外部容器提供了。

了解了IOC的基本理念后

剩下的问题就是:怎么样把类中依赖的对象的引用传递给类?(我们把这种将依赖对象的引用传递给类的方式叫做注入)

接下来,我们需要研究,有几种方法,可以把对象注入到类的内部

注入的三种方式:

1. 通过接口注入

  这种方式要求我们自己定义的组建类必须实现容器给定的一个接口,然后容器通过这个接口,为我们的组建类注入所依赖的类

  缺点:容器对组建的侵入性会很强,实现的组建只能给此容器用了,移植性不强

2. Setter注入

  在容器中,通过调用对象的setter()方法,将该对象的依赖传递到类当中

3.构造器注入

 通过使用构造器,在类初始化的时候,传入对象的依赖

知道了在容器中可以有三种方式把一个类的对象的依赖传入到这个对象的当中去,但是,这个类的对象我们到底该怎么得到呢?它的依赖又该怎么得到呢?

难道也是在容器中,简单的通过new得到不同的对象,然后进行相互调用吗?

如果是这样的话,那么我们仅仅只是完成了一些基于依赖倒转的代码重构工作而已,并没有真正的体现系统的动态性

那么我们该怎么样才能最大程度的体现系统的动态性? 怎么样才能最大程度的将两个类之间的依赖降低,实现解耦合呢?

我们可以给系统一个XML的配置文件,

在该XML配置文件中,设置每个对象的相应的属性信息(即该类的具体依赖)

然后在系统中,解析XML文件得到一个实体类obj类,obj类保留没一个对象的配置信息

然后根据反射原理,利用解析得到的obj类中信息,动态的生成配置对应的对象,并且调用对象的setter()方法,完成对该对象的注入,

因为XML只是一个符合一定格式要求的文本文件,

所以我们可以随时更改XML文件,而不修改源代码

来得到我们需要的任何类型的任何一个对象,并完全对该对象的注入

使该对象的依赖得以进行,并能使系统最大程度的动态化,具有可拓展性

IoC核心理念:

1.在类当中不创建对象,在代码中不直接与对象和服务连接

2.在配置文件中描述创建对象的方式,以及各个组件之间的联系

3.外部容器通过解析配置文件,通过反射来将这些联系在一起

The Hollywood principle:Don’t call us,we’ll call you.

即,所有组件都是被动的、不主动联系(调用)外部代码,

要等着外部代码的调用--------所有的组件的初始化和相互调用都由容器负责实现。

简单的说,就是整个程序之间的关系,都由容器来控制:将程序的控制权反转给容器,就是所谓的外转

而在我们传统代码中,由程序代码直接控制

最后,使用一个比较形象的例子来最后阐述一次IOC的作用:

所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。

那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。

Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

IoC的一个重点,是在系统运行中动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

附注:因为参考的文章和Blog太多,无法一一表示感谢.谨在此特别感谢CSDN博客的it_man大神

http://www.zhuoda.org/xiaoming/66303.html的作者

以及百度百科作者、维基百科作者

以及javaeye上的多为写了ioc的兄弟

恩,IOC原理折腾了一天总算搞明白了。接下来自己动手写个玩具Spring吧。

url: http://java-mzd.iteye.com/blog/818344

Hash表分析以及Java实现

Posted on

Hash表分析以及Java实现

Hash表分析以及Java实现

文章分类**:综合技术**

   这篇博客主要探讨**Hash****表**中的一些原理/概念,及根据这些原理/概念,自己设计一个用来存放/查找数据的Hash表,并且与JDK中的HashMap类进行比较。

我们分一下七个步骤来进行。

一。** Hash**表概念

二**. Hash**构造函数的方法,及适用范围

三**. Hash**处理冲突方法,各自特征

四**. Hash**查找过程

五**. 实现一个使用Hash存数据的场景-------Hash**查找算法,插入算法

六**. JDKHashMap**的实现

七**. Hash表与HashMap**的对比,性能分析

一。** Hash表概念 **

           在查找表中我们已经说过,在Hash表中,**记录在表中的位置和其关键字之间存在着一种确定的关系**。这样       我们就能预先知道所查关键字在表中的位置,从而直接通过下标找到记录。使ASL趋近与0.



          1) **  **哈希(Hash)函数是一个映象,即: 将关键字的集合映射到某个地址集合上,它的设置很灵活,只要这个地       址集合的大小不超出允许范围即可;

         2)  由于哈希函数是一个压缩映象,因此,在一般情况下,很容易产生“冲突”现象,即: key1¹ key2,而  f            (key1) = f(key2)。

          3).  只能尽量减少冲突而不能完全避免冲突,这是因为通常关键字集合比较大,其元素包括所有可能的关键字,       而地址集合的元素仅为哈希表中的地址值



   在构造这种特殊的“查找表” 时,除了需要选择一个**“****好****”(****尽可能少产生冲突****)**的哈希函数之外;还需要找到一      种**“****处理冲突****”** 的方法。

二**. Hash**构造函数的方法,及适用范围

§ 直接定址法

§ 数字分析法

§ 平方取中法

§ 折叠法

§ 除留余数法

§ 随机数法

  (1)直接定址法:

            哈希函数为关键字的线性函数,H(key) = key 或者 H(key) = a ´ key + b

          **此法仅适合于**:地址集合的大小 = = 关键字集合的大小,其中a和b为常数。

 (2)数字分析法:

         假设关键字集合中的每个关键字都是由 s 位数字组成 (u1, u2, …, us),分析关键字集中的全体,                  并从中提取分布均匀的若干位或它们的组合作为地址。

         **此法适于:**能预先估计出全体关键字的每一位上各种数字出现的频度。

 (3)平方取中法:

           以关键字的平方值的中间几位作为存储地址。求“关键字的平方值” 的目的是“扩大差别” ,同                    时平方值的中间各位又能受到整个关键字中各位的影响。

         **此法适于:**关键字中的每一位都有某些数字重复出现频度很高的现象。

 (4)折叠法:

        将关键字分割成若干部分,然后取它们的叠加和为哈希地址。两种叠加处理的方法:移位叠加:将分                割后的几部分低位对齐相加;间界叠加:从一端沿分割界来回折叠,然后对齐相加。

        **此法适于:**关键字的数字位数特别多。

 (5)除留余数法:

         设定哈希函数为:H(key) = key MOD p   ( p≤m ),其中, m为表长,p 为不大于 m 的素数,或                 是不含 20 以下的质因子

 (6)随机数法:

       设定哈希函数为:H(key) = Random(key)其中,Random 为伪随机函数

       **此法适于:**对长度不等的关键字构造哈希函数。



     实际造表时,采用何种构造哈希函数的方法取决于建表的关键字集合的情况(包括关键字的范围和形态),以及哈希表    长度(哈希地址范围),**总的原则是使产生冲突的可能性降到尽可能地小。**

三**. Hash**处理冲突方法,各自特征

“**处理冲突” 的实际含义是:为产生冲突的关键字寻找下一个哈希地址。**

§ **开放定址法**

§ **再哈希法**

§ **链地址法**

  (1)开放定址法:

           为产生冲突的关键字地址 H(key) 求得一个地址序列: H0, H1, H2, …, Hs  1≤s≤m-1,Hi = ( H(key)                 +di  ) MOD m,其中: i=1, 2, …, s,H(key)为哈希函数;m为哈希表长;



  (2)链地址法:

http://dl.iteye.com/upload/attachment/355453/2a1ac1de-80ef-33d5-a120-9a8f07dbf3e9.jpg

         将所有哈希地址相同的记录都链接在同一链表中。



  (3)再哈希法:

           方法:构造若干个哈希函数,当发生冲突时,根据另一个哈希函数计算下一个哈希地址,直到冲突不再发                  生。即:Hi=Rhi(key)     i=1,2,……k,其中:Rhi——不同的哈希函数,特点:计算时间增加

四**. Hash**查找过程

http://dl.iteye.com/upload/attachment/355455/a946abd8-ba7b-3e4e-b5a5-b94059e086ac.png

对于给定值 K,计算哈希地址 i = H(K),若 r[i] = NULL 则查找不成功,若 r[i].key = K 则查找成功, 否则 “求 下一地址 Hi” ,直至r[Hi] = NULL (查找不成功) 或r[Hi].key = K (查找成功) 为止。

五**. 实现一个使用Hash存数据的场景-------Hash**查找算法,插入算法

     假设我们要设计的是一个用来保存中南大学所有在校学生个人信息的数据表。因为在校学生数量也不是特别巨大(8W?),每个学生的学号是唯一的,因此,我们可以简单的应用直接定址法,声明一个10W大小的数组,每个学生的学号作为主键。然后每次要添加或者查找学生,只需要根据需要去操作即可。

  但是,显然这样做是**很脑残**的。这样做系统的可拓展性和复用性就非常差了,比如有一天人数超过10W了?如果是用来保存别的数据呢?或者我只需要保存20条记录呢?声明大小为10W的数组显然是太浪费了的。



 如果我们是用来保存大数据量(比如银行的用户数,4大的用户数都应该有3-5亿了吧?),这时候我们计算出来的HashCode就很可能会有冲突了, 我们的系统应该有“处理冲突”的能力,此处我们**通过挂链法****“****处理冲突****”**。



 如果我们的数据量非常巨大,并且还持续在增加,如果我们仅仅只是通过挂链法来处理冲突,可能我们的链上挂了上万个数据后,这个时候再通过静态搜索来查找链表,显然性能也是非常低的。所以我们的系统应该还能实现自动扩容,**当容量达到某比例后,即自动扩容,使装载因子保存在一个固定的水平上**。

综上所述,我们对这个Hash容器的基本要求应该有如下几点:

         **满足****Hash****表的查找要求(废话)**

**能支持从小数据量到大数据量的自动转变(自动扩容)**

**使用挂链法解决冲突**

好了,既然都分析到这一步了,咱就闲话少叙,直接开始上代码吧。

Java**代码 [收藏代码]()****

  1. package cn.javamzd.collection.search;

  2. public class MyMap {

  3. private int size;// 当前容量

  4. private static int INIT_CAPACITY = 16;// 默认容量

  5. private Entry[] container;// 实际存储数据的数组对象

  6. private static float LOAD_FACTOR = 0.75f;// 装载因子

  7. private int max;// 能存的最大的数=capacity/*factor

  8. // 自己设置容量和装载因子的构造器

  9. public MyMap(int init_Capaticy, float load_factor) {

  10. if (init_Capaticy < 0)

  11. throw new IllegalArgumentException("Illegal initial capacity: "

    • init_Capaticy);
  12. if (load_factor <= 0 || Float.isNaN(load_factor))

  13. throw new IllegalArgumentException("Illegal load factor: "

    • load_factor);
  14. this.LOAD_FACTOR = load_factor;

  15. max = (int) (init_Capaticy /* load_factor);

  16. container = new Entry[init_Capaticy];

  17. }

  18. // 使用默认参数的构造器

  19. public MyMap() {

  20. this(INIT_CAPACITY, LOAD_FACTOR);

  21. }

  22. ///

  23. /* 存

  24. /*

  25. /* @param k

  26. /* @param v

  27. /* @return

  28. /*/

  29. public boolean put(K k, V v) {

  30. // 1.计算K的hash值

  31. // 因为自己很难写出对不同的类型都适用的Hash算法,故调用JDK给出的hashCode()方法来计算hash值

  32. int hash = k.hashCode();

  33. //将所有信息封装为一个Entry

  34. Entry temp=new Entry(k,v,hash);

  35. if(setEntry(temp, container)){

  36. // 大小加一

  37. size++;

  38. return true;

  39. }

  40. return false;

  41. }

  42. ///

  43. /* 扩容的方法

  44. /*

  45. /* @param newSize

  46. /* 新的容器大小

  47. /*/

  48. private void reSize(int newSize) {

  49. // 1.声明新数组

  50. Entry[] newTable = new Entry[newSize];

  51. max = (int) (newSize /* LOAD_FACTOR);

  52. // 2.复制已有元素,即遍历所有元素,每个元素再存一遍

  53. for (int j = 0; j < container.length; j++) {

  54. Entry entry = container[j];

  55. //因为每个数组元素其实为链表,所以…………

  56. while (null != entry) {

  57. setEntry(entry, newTable);

  58. entry = entry.next;

  59. }

  60. }

  61. // 3.改变指向

  62. container = newTable;

  63. }

  64. ///

  65. /*将指定的结点temp添加到指定的hash表table当中

  66. /* 添加时判断该结点是否已经存在

  67. /* 如果已经存在,返回false

  68. /* 添加成功返回true

  69. /* @param temp

  70. /* @param table

  71. /* @return

  72. /*/

  73. private boolean setEntry(Entry temp,Entry[] table){

  74. // 根据hash值找到下标

  75. int index = indexFor(temp.hash, table.length);

  76. //根据下标找到对应元素

  77. Entry entry = table[index];

  78. // 3.若存在

  79. if (null != entry) {

  80. // 3.1遍历整个链表,判断是否相等

  81. while (null != entry) {

  82. //判断相等的条件时应该注意,除了比较地址相同外,引用传递的相等用equals()方法比较

  83. //相等则不存,返回false

  84. if ((temp.key == entry.key||temp.key.equals(entry.key)) && temp.hash == entry.hash&&(temp.value==entry.value||temp.value.equals(entry.value))) {

  85. return false;

  86. }

  87. //不相等则比较下一个元素

  88. else if (temp.key != entry.key && temp.value != entry.value) {

  89. //到达队尾,中断循环

  90. if(null==entry.next){

  91. break;

  92. }

  93. // 没有到达队尾,继续遍历下一个元素

  94. entry = entry.next;

  95. }

  96. }

  97. // 3.2当遍历到了队尾,如果都没有相同的元素,则将该元素挂在队尾

  98. addEntry2Last(entry,temp);

  99. }

  100. // 4.若不存在,直接设置初始化元素

  101. setFirstEntry(temp,index,table);

  102. return true;

  103. }

  104. private void addEntry2Last(Entry entry, Entry temp) {

  105. if (size > max) {

  106. reSize(container.length /* 4);

  107. }

  108. entry.next=temp;

  109. }

  110. ///

  111. /* 将指定结点temp,添加到指定的hash表table的指定下标index中

  112. /* @param temp

  113. /* @param index

  114. /* @param table

  115. /*/

  116. private void setFirstEntry(Entry temp, int index, Entry[] table) {

  117. // 1.判断当前容量是否超标,如果超标,调用扩容方法

  118. if (size > max) {

  119. reSize(table.length /* 4);

  120. }

  121. // 2.不超标,或者扩容以后,设置元素

  122. table[index] = temp;

  123. //!!!!!!!!!!!!!!!

  124. //因为每次设置后都是新的链表,需要将其后接的结点都去掉

  125. //NND,少这一行代码卡了哥哥7个小时(代码重构)

  126. temp.next=null;

  127. }

  128. ///

  129. /* 取

  130. /*

  131. /* @param k

  132. /* @return

  133. /*/

  134. public V get(K k) {

  135. Entry entry = null;

  136. // 1.计算K的hash值

  137. int hash = k.hashCode();

  138. // 2.根据hash值找到下标

  139. int index = indexFor(hash, container.length);

  140. // 3。根据index找到链表

  141. entry = container[index];

  142. // 3。若链表为空,返回null

  143. if (null == entry) {

  144. return null;

  145. }

  146. // 4。若不为空,遍历链表,比较k是否相等,如果k相等,则返回该value

  147. while (null != entry) {

  148. if (k == entry.key||entry.key.equals(k)) {

  149. return entry.value;

  150. }

  151. entry = entry.next;

  152. }

  153. // 如果遍历完了不相等,则返回空

  154. return null;

  155. }

  156. ///

  157. /* 根据hash码,容器数组的长度,计算该哈希码在容器数组中的下标值

  158. /*

  159. /* @param hashcode

  160. /* @param containerLength

  161. /* @return

  162. /*/

  163. public int indexFor(int hashcode, int containerLength) {

  164. return hashcode & (containerLength - 1);

  165. }

  166. ///

  167. /* 用来实际保存数据的内部类,因为采用挂链法解决冲突,此内部类设计为链表形式

  168. /*

  169. /* @param key

  170. /* @param

  171. /* value

  172. /*/

  173. class Entry {

  174. Entry next;// 下一个结点

  175. K key;// key

  176. V value;// value

  177. int hash;// 这个key对应的hash码,作为一个成员变量,当下次需要用的时候可以不用重新计算

  178. // 构造方法

  179. Entry(K k, V v, int hash) {

  180. this.key = k;

  181. this.value = v;

  182. this.hash = hash;

  183. }

  184. //相应的getter()方法

  185. }

  186. }

代码中有相当清楚的注释了

在文章的最后这里,我要强烈的宣泄下感情

MLGBD,本来以为分析的挺到位了,写出这个东西也就最多需要个把小时吧

结果因为通宵作业,脑袋运转不灵

硬是花了哥三个小时才写出了

好不容易些出来了

我日

看着代码比较混乱

然后就对代码重构了下

把逻辑抽象清楚,进行重构就花了个多小时

好不容易构造好了

就开始了TMD的一直报错了----------大数据量测试时到大概5000就死循环了

各种调试,各种分析都觉得没错误

最后花了哥7个小时终于找出来了

我擦

第一次初始化加的时候,因为每个元素的next都是空的

而扩充容量resize()时,因为冲突处理是链式结构的

当将他们重新hash添加的时候,重复的这些鸟元素的next是有元素的

一定要设置为null

七**.**性能分析:

  1.因为冲突的存在,其查找长度不可能达到O(1)

  2哈希表的平均查找长度是装载因子a 的函数,而不是 n 的函数。

  3.用哈希表构造查找表时,可以选择一个适当的装填因子 a ,使得平均查找长度限定在某个范围内。

最后给出我们这个HashMap的性能

测试代码

Java**代码 [收藏代码]()****

  1. public class Test {

  2. public static void main(String[] args) {

  3. MyMap mm = new MyMap();

  4. Long aBeginTime=System.currentTimeMillis();//记录BeginTime

  5. for(int i=0;i<1000000;i++){

  6. mm.put(""+i, ""+i/*100);

  7. }

  8. Long aEndTime=System.currentTimeMillis();//记录EndTime

  9. System.out.println("insert time-->"+(aEndTime-aBeginTime));

  10. Long lBeginTime=System.currentTimeMillis();//记录BeginTime

  11. mm.get(""+100000);

  12. Long lEndTime=System.currentTimeMillis();//记录EndTime

  13. System.out.println("seach time--->"+(lEndTime-lBeginTime));

  14. }

  15. }

    100W个数据时,全部存储时间为1S多一点,而搜寻时间为**0 **

insert time-->1536 seach time--->0

好了,牢骚发完了

本来今天想写个有关大访问量处理的一些基本概念的文章

全泡汤了,明天写吧

url: http://java-mzd.iteye.com/blog/827523

SQL解析(Jsqlparser)

Posted on

SQL解析(Jsqlparser)

前段时间主要研究了一下SQL语句的解析,主要的几个开源产品试用了一下。本文大概总结一下个人体会。 首先是ZQL,ZQL有个比较突出的优点是使用起来比较简单,基本上属于拿上手就可以用的。但支持的功能有限,selectItem可以是简单的表达式,但不支持查询作为一个selectItem,对于其他的子查询同样也不支持。 最终我选择使用了Jsqlparser,主要原因有两点: 1)功能强大,基本上能够覆盖所有的SQL语法(没有研究是不是包含了数据库特殊的关键字,如LIMIT ),包含UNION,GROUP BY,HAVING,ORDER BY,JOIN,SUB JOIN,SUB SELECT,FUNCTION等。支持SQL深层嵌套。 2)本身设计不错,使用起来感觉很灵活。Jsqlparser对于SQL的遍历采用了VISITOR模式可以很方便的遍历SQL语句。 下面主要介绍一下Jsqlparser在我的项目中的应用情况。 背景:通过SQL语句的解析,从而增强SQL语句增加特定的查询过滤条件(如:状态过滤、权限过滤等) 1)解析SQL 2)根据SQL中涉及的表增强SQL 3)重新生成ORACLE数据库的SQL Java代码 收藏代码

  1. CCJSqlParserManager parserManager = new CCJSqlParserManager();
  2. try {
  3. Select select = (Select) parserManager.parse(new StringReader(sql)); //解析SQL语句
  4. SelectBody body = select.getSelectBody();
  5. VisitContext vc = new VisitContext(filterContext, params);
  6. vc.setTableFilterFactory(tableFilterFactory);//表的字段过滤
  7. body.accept(new SelectVisitorImpl(vc)); //访问SQL并根据SQL中涉及的表来增强SQL
  8. ExpressionDeParser expressionDeParser = new ExpressionDeParser();
  9. StringBuffer stringBuffer = new StringBuffer();
  10. SelectDeParser deParser = new OracleSelectDeParser(expressionDeParser, stringBuffer); //针对ORACLE的SQL生成
  11. expressionDeParser.setSelectVisitor(deParser);
  12. expressionDeParser.setBuffer(stringBuffer);
  13. body.accept(deParser);
  14. return new FilterResult(deParser.getBuffer().toString(), vc.getResultSqlParams());
  15. } catch (JSQLParserException e) {
  16. throw new FilterException(e);
  17. }

     CCJSqlParserManager parserManager = new CCJSqlParserManager();
    
     try {
         Select select = (Select) parserManager.parse(new StringReader(sql)); //解析SQL语句
    
         SelectBody body = select.getSelectBody();
         VisitContext vc = new VisitContext(filterContext, params);
    
         vc.setTableFilterFactory(tableFilterFactory);//表的字段过滤
         body.accept(new SelectVisitorImpl(vc)); //访问SQL并根据SQL中涉及的表来增强SQL
    
         ExpressionDeParser expressionDeParser = new ExpressionDeParser();
         StringBuffer stringBuffer = new StringBuffer();
    
         SelectDeParser deParser = new OracleSelectDeParser(expressionDeParser, stringBuffer); //针对ORACLE的SQL生成
         expressionDeParser.setSelectVisitor(deParser);
    
         expressionDeParser.setBuffer(stringBuffer);
    
        body.accept(deParser);
        return new FilterResult(deParser.getBuffer().toString(), vc.getResultSqlParams());

    } catch (JSQLParserException e) {
        throw new FilterException(e);

    }

接下去是各个VISITOR,用来访问解析后的SQL Java代码 收藏代码

  1. public class SelectVisitorImpl extends AbstractVisitor implements SelectVisitor {
  2. public SelectVisitorImpl(VisitContext ctx) {
  3. super(ctx);
  4. }
  5. @SuppressWarnings("unchecked")
  6. public void visit(PlainSelect ps) {
  7. //SELECT ITEM访问
  8. List selectItems = ps.getSelectItems();
  9. for (SelectItem item : selectItems) {
  10. item.accept(new SelectItemVisitorImpl(this.getContext()));
  11. }
  12. //FROM访问
  13. FromItem from = ps.getFromItem();
  14. FromItemVisitorImpl fv = new FromItemVisitorImpl(context);
  15. from.accept(fv);
  16. //查询条件访问
  17. if (ps.getWhere() != null) {
  18. ps.getWhere().accept(new ExpressionVisitorImpl(this.getContext()));
  19. }
  20. //过滤增强的条件
  21. if (fv.getEnhancedCondition() != null) {
  22. if (ps.getWhere() != null) {
  23. Expression expr = new Parenthesis(ps.getWhere());
  24. AndExpression and = new AndExpression(fv.getEnhancedCondition(), expr);
  25. ps.setWhere(and);
  26. } else {
  27. ps.setWhere(fv.getEnhancedCondition());
  28. }
  29. }
  30. //JOIN表的访问
  31. List joins = ps.getJoins();
  32. if (CollectionUtil.isNotEmpty(joins)) {
  33. for (Join join : joins) {
  34. FromItemVisitorImpl tempfv = new FromItemVisitorImpl(context);
  35. join.getRightItem().accept(tempfv);
  36. if (join.getOnExpression() != null) {
  37. join.getOnExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  38. if (tempfv.getEnhancedCondition() != null) {
  39. Expression expr = new Parenthesis(join.getOnExpression());
  40. AndExpression and = new AndExpression(tempfv.getEnhancedCondition(), expr);
  41. join.setOnExpression(and);
  42. }
  43. }
  44. }
  45. }
  46. //ORDER BY 访问
  47. List elements = ps.getOrderByElements();
  48. if (CollectionUtil.isNotEmpty(elements)) {
  49. for (OrderByElement e : elements) {
  50. e.getExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  51. }
  52. }
  53. //GROUP BY的HAVING访问
  54. if (ps.getHaving() != null) {
  55. ps.getHaving().accept(new ExpressionVisitorImpl(this.getContext()));
  56. }
  57. }
  58. @SuppressWarnings("unchecked")
  59. public void visit(Union un) {
  60. List selects = un.getPlainSelects();
  61. for (PlainSelect select : selects) {
  62. select.accept(new SelectVisitorImpl(this.getContext()));
  63. }
  64. List elements = un.getOrderByElements();
  65. if (CollectionUtil.isNotEmpty(elements)) {
  66. for (OrderByElement e : elements) {
  67. e.getExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  68. }
  69. }
  70. }
  71. }

public class SelectVisitorImpl extends AbstractVisitor implements SelectVisitor {

public SelectVisitorImpl(VisitContext ctx) {

    super(ctx);
}


@SuppressWarnings("unchecked")

public void visit(PlainSelect ps) {
    //SELECT ITEM访问

    List<SelectItem> selectItems = ps.getSelectItems();
    for (SelectItem item : selectItems) {

        item.accept(new SelectItemVisitorImpl(this.getContext()));
    }


    //FROM访问

    FromItem from = ps.getFromItem();
    FromItemVisitorImpl fv = new FromItemVisitorImpl(context);

    from.accept(fv);


    //查询条件访问
    if (ps.getWhere() != null) {

        ps.getWhere().accept(new ExpressionVisitorImpl(this.getContext()));
    }


    //过滤增强的条件

    if (fv.getEnhancedCondition() != null) {
        if (ps.getWhere() != null) {

            Expression expr = new Parenthesis(ps.getWhere());
            AndExpression and = new AndExpression(fv.getEnhancedCondition(), expr);

            ps.setWhere(and);
        } else {

            ps.setWhere(fv.getEnhancedCondition());
        }

    }


    //JOIN表的访问
    List<Join> joins = ps.getJoins();

    if (CollectionUtil.isNotEmpty(joins)) {
        for (Join join : joins) {

            FromItemVisitorImpl tempfv = new FromItemVisitorImpl(context);
            join.getRightItem().accept(tempfv);

            if (join.getOnExpression() != null) {
                join.getOnExpression().accept(new ExpressionVisitorImpl(this.getContext()));

                if (tempfv.getEnhancedCondition() != null) {
                    Expression expr = new Parenthesis(join.getOnExpression());

                    AndExpression and = new AndExpression(tempfv.getEnhancedCondition(), expr);
                    join.setOnExpression(and);

                }
            }

        }
    }


    //ORDER BY 访问

    List<OrderByElement> elements = ps.getOrderByElements();
    if (CollectionUtil.isNotEmpty(elements)) {

        for (OrderByElement e : elements) {
            e.getExpression().accept(new ExpressionVisitorImpl(this.getContext()));

        }
    }


    //GROUP BY的HAVING访问

    if (ps.getHaving() != null) {
        ps.getHaving().accept(new ExpressionVisitorImpl(this.getContext()));

    }
}


@SuppressWarnings("unchecked")

public void visit(Union un) {
    List<PlainSelect> selects = un.getPlainSelects();

    for (PlainSelect select : selects) {
        select.accept(new SelectVisitorImpl(this.getContext()));

    }
    List<OrderByElement> elements = un.getOrderByElements();

    if (CollectionUtil.isNotEmpty(elements)) {
        for (OrderByElement e : elements) {

            e.getExpression().accept(new ExpressionVisitorImpl(this.getContext()));
        }

    }
}

} Java代码 收藏代码

  1. public class SelectItemVisitorImpl extends AbstractVisitor implements SelectItemVisitor {
  2. public SelectItemVisitorImpl(VisitContext ctx) {
  3. super(ctx);
  4. }
  5. public void visit(AllColumns ac) {
  6. }
  7. public void visit(AllTableColumns atc) {
  8. }
  9. public void visit(SelectExpressionItem sei) {
  10. sei.getExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  11. }
  12. }

public class SelectItemVisitorImpl extends AbstractVisitor implements SelectItemVisitor {

public SelectItemVisitorImpl(VisitContext ctx) {

    super(ctx);
}


public void visit(AllColumns ac) {

}


public void visit(AllTableColumns atc) {
}


public void visit(SelectExpressionItem sei) {

    sei.getExpression().accept(new ExpressionVisitorImpl(this.getContext()));
}

} Java代码 收藏代码

  1. public class ItemsListVisitorImpl extends AbstractVisitor implements ItemsListVisitor {
  2. public ItemsListVisitorImpl(VisitContext ctx) {
  3. super(ctx);
  4. }
  5. public void visit(SubSelect ss) {
  6. ss.getSelectBody().accept(new SelectVisitorImpl(context));
  7. }
  8. @SuppressWarnings("unchecked")
  9. public void visit(ExpressionList el) {
  10. List list = el.getExpressions();
  11. if (CollectionUtil.isNotEmpty(list)) {
  12. for (Expression expr : list) {
  13. expr.accept(new ExpressionVisitorImpl(context));
  14. }
  15. }
  16. }
  17. }

public class ItemsListVisitorImpl extends AbstractVisitor implements ItemsListVisitor {

public ItemsListVisitorImpl(VisitContext ctx) {

    super(ctx);
}


public void visit(SubSelect ss) {

    ss.getSelectBody().accept(new SelectVisitorImpl(context));
}


@SuppressWarnings("unchecked")

public void visit(ExpressionList el) {
    List<Expression> list = el.getExpressions();

    if (CollectionUtil.isNotEmpty(list)) {
        for (Expression expr : list) {

            expr.accept(new ExpressionVisitorImpl(context));
        }

    }
}

} 如果FROM的内容是table的话,则根据table的增强配置对SQL增强 Java代码 收藏代码

  1. public class FromItemVisitorImpl extends AbstractVisitor implements FromItemVisitor {
  2. private String varPattern = "@\{\s/?(\w+)\s/?\}";
  3. private Expression enhancedCondition;
  4. public FromItemVisitorImpl(VisitContext ctx) {
  5. super(ctx);
  6. }
  7. public void visit(Table table) {
  8. Set filters = context.getTableFilterFactory().getTableFilter(table.getName());
  9. if (filters == null) {
  10. filters = Collections.emptySet();
  11. }
  12. for (FieldFilter ff : filters) {
  13. Column c = new Column(new Table(null, table.getAlias()), ff.getFieldName());
  14. JdbcParameter param = new JdbcParameter();
  15. Object fieldValue = getRawValue(ff.getFieldValue(), this.context.getFilterContext());
  16. Expression[] exps;
  17. if ("between".equalsIgnoreCase(ff.getOperator()) || "not between".equalsIgnoreCase(ff.getOperator())) {
  18. Object[] objs = (Object[]) fieldValue;
  19. this.getContext().getResultSqlParams().add(objs[0]);
  20. this.getContext().getResultSqlParams().add(objs[1]);
  21. exps = new Expression[] { c, param, param };
  22. } else if ("is null".equalsIgnoreCase(ff.getOperator()) || "is not null".equalsIgnoreCase(ff.getOperator())) {
  23. exps = new Expression[] { c };
  24. } else {
  25. this.getContext().getResultSqlParams().add(fieldValue);
  26. exps = new Expression[] { c, param };
  27. }
  28. Expression operator = this.getOperator(ff.getOperator(), exps);
  29. if (this.enhancedCondition != null) {
  30. enhancedCondition = new AndExpression(enhancedCondition, operator);
  31. } else {
  32. enhancedCondition = operator;
  33. }
  34. }
  35. }
  36. public void visit(SubSelect ss) {
  37. ss.getSelectBody().accept(new SelectVisitorImpl(this.getContext()));
  38. }
  39. public void visit(SubJoin sj) {
  40. Join join = sj.getJoin();
  41. join.getRightItem().accept(new FromItemVisitorImpl(this.getContext()));
  42. join.getOnExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  43. }
  44. private Expression getOperator(String op, Expression[] exp) {
  45. if ("=".equals(op)) {
  46. EqualsTo eq = new EqualsTo();
  47. eq.setLeftExpression(exp[0]);
  48. eq.setRightExpression(exp[1]);
  49. return eq;
  50. } else if (">".equals(op)) {
  51. GreaterThan gt = new GreaterThan();
  52. gt.setLeftExpression(exp[0]);
  53. gt.setRightExpression(exp[1]);
  54. return gt;
  55. } else if (">=".equals(op)) {
  56. GreaterThanEquals geq = new GreaterThanEquals();
  57. geq.setLeftExpression(exp[0]);
  58. geq.setRightExpression(exp[1]);
  59. return geq;
  60. } else if ("<".equals(op)) {
  61. MinorThan mt = new MinorThan();
  62. mt.setLeftExpression(exp[0]);
  63. mt.setRightExpression(exp[1]);
  64. return mt;
  65. } else if ("<=".equals(op)) {
  66. MinorThanEquals leq = new MinorThanEquals();
  67. leq.setLeftExpression(exp[0]);
  68. leq.setRightExpression(exp[1]);
  69. return leq;
  70. } else if ("<>".equals(op)) {
  71. NotEqualsTo neq = new NotEqualsTo();
  72. neq.setLeftExpression(exp[0]);
  73. neq.setRightExpression(exp[1]);
  74. return neq;
  75. } else if ("is null".equalsIgnoreCase(op)) {
  76. IsNullExpression isNull = new IsNullExpression();
  77. isNull.setNot(false);
  78. isNull.setLeftExpression(exp[0]);
  79. return isNull;
  80. } else if ("is not null".equalsIgnoreCase(op)) {
  81. IsNullExpression isNull = new IsNullExpression();
  82. isNull.setNot(true);
  83. isNull.setLeftExpression(exp[0]);
  84. return isNull;
  85. } else if ("like".equalsIgnoreCase(op)) {
  86. LikeExpression like = new LikeExpression();
  87. like.setNot(false);
  88. like.setLeftExpression(exp[0]);
  89. like.setRightExpression(exp[1]);
  90. return like;
  91. } else if ("not like".equalsIgnoreCase(op)) {
  92. LikeExpression nlike = new LikeExpression();
  93. nlike.setNot(true);
  94. nlike.setLeftExpression(exp[0]);
  95. nlike.setRightExpression(exp[1]);
  96. return nlike;
  97. } else if ("between".equalsIgnoreCase(op)) {
  98. Between bt = new Between();
  99. bt.setNot(false);
  100. bt.setLeftExpression(exp[0]);
  101. bt.setBetweenExpressionStart(exp[1]);
  102. bt.setBetweenExpressionEnd(exp[2]);
  103. return bt;
  104. } else if ("not between".equalsIgnoreCase(op)) {
  105. Between bt = new Between();
  106. bt.setNot(true);
  107. bt.setLeftExpression(exp[0]);
  108. bt.setBetweenExpressionStart(exp[1]);
  109. bt.setBetweenExpressionEnd(exp[2]);
  110. return bt;
  111. }
  112. throw new FilterException("Unknown operator:" + op);
  113. }
  114. protected Object getRawValue(Object value, Map context) {
  115. if (context == null) {
  116. return value;
  117. }
  118. if (value instanceof String) {
  119. String v = (String) value;
  120. Pattern pattern = Pattern.compile(varPattern);
  121. Matcher matcher = pattern.matcher(v);
  122. if (matcher.find()) {
  123. return context.get(matcher.group(1));
  124. }
  125. }
  126. return value;
  127. }
  128. public Expression getEnhancedCondition() {
  129. return enhancedCondition;
  130. }
  131. }

public class FromItemVisitorImpl extends AbstractVisitor implements FromItemVisitor {

private String varPattern = "@\\{\\s/*?(\\w+)\\s/*?\\}";
private Expression enhancedCondition;


public FromItemVisitorImpl(VisitContext ctx) {

    super(ctx);
}


public void visit(Table table) {

    Set<FieldFilter> filters = context.getTableFilterFactory().getTableFilter(table.getName());
    if (filters == null) {

        filters = Collections.emptySet();
    }

    for (FieldFilter ff : filters) {
        Column c = new Column(new Table(null, table.getAlias()), ff.getFieldName());

        JdbcParameter param = new JdbcParameter();
        Object fieldValue = getRawValue(ff.getFieldValue(), this.context.getFilterContext());

        Expression[] exps;
        if ("between".equalsIgnoreCase(ff.getOperator()) || "not between".equalsIgnoreCase(ff.getOperator())) {

            Object[] objs = (Object[]) fieldValue;
            this.getContext().getResultSqlParams().add(objs[0]);

            this.getContext().getResultSqlParams().add(objs[1]);
            exps = new Expression[] { c, param, param };

        } else if ("is null".equalsIgnoreCase(ff.getOperator()) || "is not null".equalsIgnoreCase(ff.getOperator())) {
            exps = new Expression[] { c };

        } else {
            this.getContext().getResultSqlParams().add(fieldValue);

            exps = new Expression[] { c, param };
        }

        Expression operator = this.getOperator(ff.getOperator(), exps);
        if (this.enhancedCondition != null) {

            enhancedCondition = new AndExpression(enhancedCondition, operator);
        } else {

            enhancedCondition = operator;
        }

    }
}


public void visit(SubSelect ss) {

    ss.getSelectBody().accept(new SelectVisitorImpl(this.getContext()));
}


public void visit(SubJoin sj) {

    Join join = sj.getJoin();
    join.getRightItem().accept(new FromItemVisitorImpl(this.getContext()));

    join.getOnExpression().accept(new ExpressionVisitorImpl(this.getContext()));
}


private Expression getOperator(String op, Expression[] exp) {

    if ("=".equals(op)) {
        EqualsTo eq = new EqualsTo();

        eq.setLeftExpression(exp[0]);
        eq.setRightExpression(exp[1]);

        return eq;
    } else if (">".equals(op)) {

        GreaterThan gt = new GreaterThan();
        gt.setLeftExpression(exp[0]);

        gt.setRightExpression(exp[1]);
        return gt;

    } else if (">=".equals(op)) {
        GreaterThanEquals geq = new GreaterThanEquals();

        geq.setLeftExpression(exp[0]);
        geq.setRightExpression(exp[1]);

        return geq;
    } else if ("<".equals(op)) {

        MinorThan mt = new MinorThan();
        mt.setLeftExpression(exp[0]);

        mt.setRightExpression(exp[1]);
        return mt;

    } else if ("<=".equals(op)) {
        MinorThanEquals leq = new MinorThanEquals();

        leq.setLeftExpression(exp[0]);
        leq.setRightExpression(exp[1]);

        return leq;
    } else if ("<>".equals(op)) {

        NotEqualsTo neq = new NotEqualsTo();
        neq.setLeftExpression(exp[0]);

        neq.setRightExpression(exp[1]);
        return neq;

    } else if ("is null".equalsIgnoreCase(op)) {
        IsNullExpression isNull = new IsNullExpression();

        isNull.setNot(false);
        isNull.setLeftExpression(exp[0]);

        return isNull;
    } else if ("is not null".equalsIgnoreCase(op)) {

        IsNullExpression isNull = new IsNullExpression();
        isNull.setNot(true);

        isNull.setLeftExpression(exp[0]);
        return isNull;

    } else if ("like".equalsIgnoreCase(op)) {
        LikeExpression like = new LikeExpression();

        like.setNot(false);
        like.setLeftExpression(exp[0]);

        like.setRightExpression(exp[1]);
        return like;

    } else if ("not like".equalsIgnoreCase(op)) {
        LikeExpression nlike = new LikeExpression();

        nlike.setNot(true);
        nlike.setLeftExpression(exp[0]);

        nlike.setRightExpression(exp[1]);
        return nlike;

    } else if ("between".equalsIgnoreCase(op)) {
        Between bt = new Between();

        bt.setNot(false);
        bt.setLeftExpression(exp[0]);

        bt.setBetweenExpressionStart(exp[1]);
        bt.setBetweenExpressionEnd(exp[2]);

        return bt;
    } else if ("not between".equalsIgnoreCase(op)) {

        Between bt = new Between();
        bt.setNot(true);

        bt.setLeftExpression(exp[0]);
        bt.setBetweenExpressionStart(exp[1]);

        bt.setBetweenExpressionEnd(exp[2]);
        return bt;

    }
    throw new FilterException("Unknown operator:" + op);

}


protected Object getRawValue(Object value, Map<String, Object> context) {
    if (context == null) {

        return value;
    }

    if (value instanceof String) {
        String v = (String) value;

        Pattern pattern = Pattern.compile(varPattern);
        Matcher matcher = pattern.matcher(v);

        if (matcher.find()) {
            return context.get(matcher.group(1));

        }
    }

    return value;
}


public Expression getEnhancedCondition() {

    return enhancedCondition;
}

} 1)对JDBC parameter做了处理,如果参数为NULL则自动忽略该parameter,忽略后需要处理and or between 等情况 如:where name=? and age=? ,假如name对应的参数为null,则条件改为where 1=1 and age=?,如果是or的话则改为 where 1=0 or age=? Java代码 收藏代码

  1. public class ExpressionVisitorImpl extends AbstractVisitor implements ExpressionVisitor {
  2. public ExpressionVisitorImpl(VisitContext ctx) {
  3. super(ctx);
  4. }
  5. public void visit(NullValue nv) {
  6. }
  7. public void visit(Function f) {
  8. }
  9. public void visit(InverseExpression ie) {
  10. }
  11. public void visit(JdbcParameter jp) {
  12. this.getContext().getResultSqlParams().add(context.removeFirstParam());
  13. }
  14. public void visit(DoubleValue dv) {
  15. }
  16. public void visit(LongValue lv) {
  17. }
  18. public void visit(DateValue dv) {
  19. }
  20. public void visit(TimeValue tv) {
  21. }
  22. public void visit(TimestampValue tv) {
  23. }
  24. public void visit(Parenthesis parenthesis) {
  25. ExpressionVisitorImpl ev = new ExpressionVisitorImpl(context);
  26. parenthesis.getExpression().accept(ev);
  27. if (ev.isNotValid()) {
  28. parenthesis.setExpression(this.createTrueEquals());
  29. }
  30. }
  31. public void visit(StringValue s) {
  32. }
  33. public void visit(Addition a) {
  34. }
  35. public void visit(Division d) {
  36. }
  37. public void visit(Multiplication m) {
  38. }
  39. public void visit(Subtraction s) {
  40. }
  41. public void visit(AndExpression and) {
  42. ExpressionVisitorImpl left = new ExpressionVisitorImpl(this.getContext());
  43. and.getLeftExpression().accept(left);
  44. if (left.isNotValid()) {
  45. and.setLeftExpression(this.createTrueEquals());
  46. }
  47. ExpressionVisitorImpl right = new ExpressionVisitorImpl(this.getContext());
  48. and.getRightExpression().accept(right);
  49. if (right.isNotValid()) {
  50. and.setRightExpression(this.createTrueEquals());
  51. }
  52. }
  53. public void visit(OrExpression or) {
  54. ExpressionVisitorImpl left = new ExpressionVisitorImpl(this.getContext());
  55. or.getLeftExpression().accept(left);
  56. if (left.isNotValid()) {
  57. or.setLeftExpression(this.createFalseEquals());
  58. }
  59. ExpressionVisitorImpl right = new ExpressionVisitorImpl(this.getContext());
  60. or.getRightExpression().accept(right);
  61. if (right.isNotValid()) {
  62. or.setRightExpression(this.createFalseEquals());
  63. }
  64. }
  65. public void visit(Between btw) {
  66. Expression start = btw.getBetweenExpressionStart();
  67. Expression end = btw.getBetweenExpressionEnd();
  68. if (start instanceof JdbcParameter && end instanceof JdbcParameter) {
  69. Object o1 = this.context.getFirstParam();
  70. Object o2 = this.context.getParam(1);
  71. if (o1 == null || o2 == null) {
  72. this.context.removeFirstParam();
  73. this.context.removeFirstParam();
  74. this.setValid(false);
  75. return;
  76. }
  77. } else if (start instanceof JdbcParameter || end instanceof JdbcParameter) {
  78. Object o1 = this.context.getFirstParam();
  79. if (o1 == null) {
  80. this.context.removeFirstParam();
  81. this.setValid(false);
  82. return;
  83. }
  84. }
  85. btw.getLeftExpression().accept(new ExpressionVisitorImpl(context));
  86. btw.getBetweenExpressionStart().accept(new ExpressionVisitorImpl(context));
  87. btw.getBetweenExpressionEnd().accept(new ExpressionVisitorImpl(context));
  88. }
  89. public void visit(EqualsTo eq) {
  90. if (eq.getRightExpression() instanceof JdbcParameter) {
  91. Object o = this.context.getFirstParam();
  92. if (o == null) {
  93. this.setValid(false);
  94. this.getContext().removeFirstParam();
  95. return;
  96. }
  97. }
  98. eq.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  99. eq.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  100. }
  101. public void visit(GreaterThan gt) {
  102. if (gt.getRightExpression() instanceof JdbcParameter) {
  103. Object o = this.context.getFirstParam();
  104. if (o == null) {
  105. this.setValid(false);
  106. this.getContext().removeFirstParam();
  107. }
  108. }
  109. gt.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  110. gt.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  111. }
  112. public void visit(GreaterThanEquals gte) {
  113. if (gte.getRightExpression() instanceof JdbcParameter) {
  114. Object o = this.context.getFirstParam();
  115. if (o == null) {
  116. this.setValid(false);
  117. this.getContext().removeFirstParam();
  118. }
  119. }
  120. gte.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  121. gte.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  122. }
  123. public void visit(InExpression in) {
  124. ItemsList list = in.getItemsList();
  125. list.accept(new ItemsListVisitorImpl(context));
  126. }
  127. public void visit(IsNullExpression ine) {
  128. }
  129. public void visit(LikeExpression le) {
  130. if (le.getRightExpression() instanceof JdbcParameter) {
  131. Object o = this.context.getFirstParam();
  132. if (o == null) {
  133. this.setValid(false);
  134. this.getContext().removeFirstParam();
  135. }
  136. }
  137. le.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  138. le.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  139. }
  140. public void visit(MinorThan mt) {
  141. if (mt.getRightExpression() instanceof JdbcParameter) {
  142. Object o = this.context.getFirstParam();
  143. if (o == null) {
  144. this.setValid(false);
  145. this.getContext().removeFirstParam();
  146. }
  147. }
  148. mt.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  149. mt.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  150. }
  151. public void visit(MinorThanEquals mte) {
  152. if (mte.getRightExpression() instanceof JdbcParameter) {
  153. Object o = this.context.getFirstParam();
  154. if (o == null) {
  155. this.setValid(false);
  156. this.getContext().removeFirstParam();
  157. }
  158. }
  159. mte.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  160. mte.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  161. }
  162. public void visit(NotEqualsTo neq) {
  163. if (neq.getRightExpression() instanceof JdbcParameter) {
  164. Object o = this.context.getFirstParam();
  165. if (o == null) {
  166. this.setValid(false);
  167. this.getContext().removeFirstParam();
  168. return;
  169. }
  170. }
  171. neq.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  172. neq.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
  173. }
  174. public void visit(Column c) {
  175. }
  176. public void visit(SubSelect ss) {
  177. ss.getSelectBody().accept(new SelectVisitorImpl(context));
  178. }
  179. public void visit(CaseExpression ce) {
  180. }
  181. public void visit(WhenClause wc) {
  182. }
  183. public void visit(ExistsExpression ee) {
  184. }
  185. public void visit(AllComparisonExpression ace) {
  186. }
  187. public void visit(AnyComparisonExpression ace) {
  188. }
  189. public void visit(Concat c) {
  190. }
  191. public void visit(Matches m) {
  192. }
  193. public void visit(BitwiseAnd ba) {
  194. }
  195. public void visit(BitwiseOr bo) {
  196. }
  197. public void visit(BitwiseXor bx) {
  198. }
  199. private EqualsTo createTrueEquals() {
  200. EqualsTo eq = new EqualsTo();
  201. eq.setLeftExpression(new LongValue("1"));
  202. eq.setRightExpression(new LongValue("1"));
  203. return eq;
  204. }
  205. private EqualsTo createFalseEquals() {
  206. EqualsTo eq = new EqualsTo();
  207. eq.setLeftExpression(new LongValue("1"));
  208. eq.setRightExpression(new LongValue("0"));
  209. return eq;
  210. }
  211. }

public class ExpressionVisitorImpl extends AbstractVisitor implements ExpressionVisitor {

public ExpressionVisitorImpl(VisitContext ctx) {

    super(ctx);
}


public void visit(NullValue nv) {

}


public void visit(Function f) {
}


public void visit(InverseExpression ie) {

}


public void visit(JdbcParameter jp) {
    this.getContext().getResultSqlParams().add(context.removeFirstParam());

}


public void visit(DoubleValue dv) {
}


public void visit(LongValue lv) {

}


public void visit(DateValue dv) {
}


public void visit(TimeValue tv) {

}


public void visit(TimestampValue tv) {
}


public void visit(Parenthesis parenthesis) {

    ExpressionVisitorImpl ev = new ExpressionVisitorImpl(context);
    parenthesis.getExpression().accept(ev);

    if (ev.isNotValid()) {
        parenthesis.setExpression(this.createTrueEquals());

    }
}


public void visit(StringValue s) {

}


public void visit(Addition a) {
}


public void visit(Division d) {

}


public void visit(Multiplication m) {
}


public void visit(Subtraction s) {

}


public void visit(AndExpression and) {
    ExpressionVisitorImpl left = new ExpressionVisitorImpl(this.getContext());

    and.getLeftExpression().accept(left);
    if (left.isNotValid()) {

        and.setLeftExpression(this.createTrueEquals());
    }

    ExpressionVisitorImpl right = new ExpressionVisitorImpl(this.getContext());
    and.getRightExpression().accept(right);

    if (right.isNotValid()) {
        and.setRightExpression(this.createTrueEquals());

    }
}


public void visit(OrExpression or) {

    ExpressionVisitorImpl left = new ExpressionVisitorImpl(this.getContext());
    or.getLeftExpression().accept(left);

    if (left.isNotValid()) {
        or.setLeftExpression(this.createFalseEquals());

    }
    ExpressionVisitorImpl right = new ExpressionVisitorImpl(this.getContext());

    or.getRightExpression().accept(right);
    if (right.isNotValid()) {

        or.setRightExpression(this.createFalseEquals());
    }

}


public void visit(Between btw) {
    Expression start = btw.getBetweenExpressionStart();

    Expression end = btw.getBetweenExpressionEnd();
    if (start instanceof JdbcParameter && end instanceof JdbcParameter) {

        Object o1 = this.context.getFirstParam();
        Object o2 = this.context.getParam(1);

        if (o1 == null || o2 == null) {
            this.context.removeFirstParam();

            this.context.removeFirstParam();
            this.setValid(false);

            return;
        }

    } else if (start instanceof JdbcParameter || end instanceof JdbcParameter) {
        Object o1 = this.context.getFirstParam();

        if (o1 == null) {
            this.context.removeFirstParam();

            this.setValid(false);
            return;

        }
    }

    btw.getLeftExpression().accept(new ExpressionVisitorImpl(context));
    btw.getBetweenExpressionStart().accept(new ExpressionVisitorImpl(context));

    btw.getBetweenExpressionEnd().accept(new ExpressionVisitorImpl(context));
}


public void visit(EqualsTo eq) {

    if (eq.getRightExpression() instanceof JdbcParameter) {
        Object o = this.context.getFirstParam();

        if (o == null) {
            this.setValid(false);

            this.getContext().removeFirstParam();
            return;

        }
    }

    eq.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
    eq.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));

}


public void visit(GreaterThan gt) {
    if (gt.getRightExpression() instanceof JdbcParameter) {

        Object o = this.context.getFirstParam();
        if (o == null) {

            this.setValid(false);
            this.getContext().removeFirstParam();

        }
    }

    gt.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
    gt.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));

}


public void visit(GreaterThanEquals gte) {
    if (gte.getRightExpression() instanceof JdbcParameter) {

        Object o = this.context.getFirstParam();
        if (o == null) {

            this.setValid(false);
            this.getContext().removeFirstParam();

        }
    }

    gte.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
    gte.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));

}


public void visit(InExpression in) {
    ItemsList list = in.getItemsList();

    list.accept(new ItemsListVisitorImpl(context));
}


public void visit(IsNullExpression ine) {

}


public void visit(LikeExpression le) {
    if (le.getRightExpression() instanceof JdbcParameter) {

        Object o = this.context.getFirstParam();
        if (o == null) {

            this.setValid(false);
            this.getContext().removeFirstParam();

        }
    }

    le.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
    le.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));

}


public void visit(MinorThan mt) {
    if (mt.getRightExpression() instanceof JdbcParameter) {

        Object o = this.context.getFirstParam();
        if (o == null) {

            this.setValid(false);
            this.getContext().removeFirstParam();

        }
    }

    mt.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
    mt.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));

}


public void visit(MinorThanEquals mte) {
    if (mte.getRightExpression() instanceof JdbcParameter) {

        Object o = this.context.getFirstParam();
        if (o == null) {

            this.setValid(false);
            this.getContext().removeFirstParam();

        }
    }

    mte.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));
    mte.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));

}


public void visit(NotEqualsTo neq) {
    if (neq.getRightExpression() instanceof JdbcParameter) {

        Object o = this.context.getFirstParam();
        if (o == null) {

            this.setValid(false);
            this.getContext().removeFirstParam();

            return;
        }

    }
    neq.getLeftExpression().accept(new ExpressionVisitorImpl(this.getContext()));

    neq.getRightExpression().accept(new ExpressionVisitorImpl(this.getContext()));
}


public void visit(Column c) {

}


public void visit(SubSelect ss) {
    ss.getSelectBody().accept(new SelectVisitorImpl(context));

}


public void visit(CaseExpression ce) {
}


public void visit(WhenClause wc) {

}


public void visit(ExistsExpression ee) {
}


public void visit(AllComparisonExpression ace) {

}


public void visit(AnyComparisonExpression ace) {
}


public void visit(Concat c) {

}


public void visit(Matches m) {
}


public void visit(BitwiseAnd ba) {

}


public void visit(BitwiseOr bo) {
}


public void visit(BitwiseXor bx) {

}


private EqualsTo createTrueEquals() {
    EqualsTo eq = new EqualsTo();

    eq.setLeftExpression(new LongValue("1"));
    eq.setRightExpression(new LongValue("1"));

    return eq;
}


private EqualsTo createFalseEquals() {

    EqualsTo eq = new EqualsTo();
    eq.setLeftExpression(new LongValue("1"));

    eq.setRightExpression(new LongValue("0"));
    return eq;

}

} 增强后SQL语句的重新生成,根据ORACLE的语法重写了几个生成的方法 Java代码 收藏代码

  1. public class OracleSelectDeParser extends SelectDeParser {
  2. public OracleSelectDeParser(ExpressionDeParser expressionDeParser, StringBuffer sb) {
  3. super(expressionDeParser, sb);
  4. }
  5. ///
  6. /* 重写父类方法,去掉父类方法中table前的as
  7. /*/
  8. public void visit(Table tableName) {
  9. buffer.append(tableName.getWholeTableName());
  10. String alias = tableName.getAlias();
  11. if (alias != null && StringUtil.isNotEmpty(alias)) {
  12. buffer.append(" ");
  13. buffer.append(alias);
  14. }
  15. }
  16. ///
  17. /* 重写父类方法,在JOIN之前增加空格
  18. /*/
  19. @SuppressWarnings("unchecked")
  20. public void deparseJoin(Join join) {
  21. if (join.isSimple()) {
  22. buffer.append(", ");
  23. } else {
  24. buffer.append(" ");
  25. if (join.isRight()) {
  26. buffer.append("RIGHT ");
  27. } else if (join.isNatural()) {
  28. buffer.append("NATURAL ");
  29. } else if (join.isFull()) {
  30. buffer.append("FULL ");
  31. } else if (join.isLeft()) {
  32. buffer.append("LEFT ");
  33. }
  34. if (join.isOuter()) {
  35. buffer.append("OUTER ");
  36. } else if (join.isInner()) {
  37. buffer.append("INNER ");
  38. }
  39. buffer.append("JOIN ");
  40. }
  41. FromItem fromItem = join.getRightItem();
  42. fromItem.accept(this);
  43. if (join.getOnExpression() != null) {
  44. buffer.append(" ON ");
  45. join.getOnExpression().accept(expressionVisitor);
  46. }
  47. if (join.getUsingColumns() != null) {
  48. buffer.append(" USING ( ");
  49. for (Iterator iterator = join.getUsingColumns().iterator(); iterator.hasNext();) {
  50. Column column = iterator.next();
  51. buffer.append(column.getWholeColumnName());
  52. if (iterator.hasNext()) {
  53. buffer.append(" ,");
  54. }
  55. }
  56. buffer.append(")");
  57. }
  58. }
  59. }

public class OracleSelectDeParser extends SelectDeParser {

public OracleSelectDeParser(ExpressionDeParser expressionDeParser, StringBuffer sb) {

    super(expressionDeParser, sb);
}


//*/*

 /* 重写父类方法,去掉父类方法中table前的as
 /*/

public void visit(Table tableName) {
    buffer.append(tableName.getWholeTableName());

    String alias = tableName.getAlias();
    if (alias != null && StringUtil.isNotEmpty(alias)) {

        buffer.append(" ");
        buffer.append(alias);

    }
}


//*/*

 /* 重写父类方法,在JOIN之前增加空格
 /*/

@SuppressWarnings("unchecked")
public void deparseJoin(Join join) {

    if (join.isSimple()) {
        buffer.append(", ");

    } else {
        buffer.append(" ");

        if (join.isRight()) {
            buffer.append("RIGHT ");

        } else if (join.isNatural()) {
            buffer.append("NATURAL ");

        } else if (join.isFull()) {
            buffer.append("FULL ");

        } else if (join.isLeft()) {
            buffer.append("LEFT ");

        }
        if (join.isOuter()) {

            buffer.append("OUTER ");
        } else if (join.isInner()) {

            buffer.append("INNER ");
        }

        buffer.append("JOIN ");
    }


    FromItem fromItem = join.getRightItem();

    fromItem.accept(this);
    if (join.getOnExpression() != null) {

        buffer.append(" ON ");
        join.getOnExpression().accept(expressionVisitor);

    }
    if (join.getUsingColumns() != null) {

        buffer.append(" USING ( ");
        for (Iterator<Column> iterator = join.getUsingColumns().iterator(); iterator.hasNext();) {

            Column column = iterator.next();
            buffer.append(column.getWholeColumnName());

            if (iterator.hasNext()) {
                buffer.append(" ,");

            }
        }

        buffer.append(")");
    }

}

}