随笔:93 文章:11 评论:22 引用:0
首页 发新随笔
发新文章 联系 聚合管理

     摘要:   Java接口和Java抽象类     在没有好好地研习面向对象设计的设计模式之前,我对Java接口和Java抽象类的认识还是很模糊,很不可理解。         刚学Java语言时,就很难理解为什么要有接口这个概念,虽说是可以实现所谓的多继承,可一个只有方法名,没有方法体的东西,...  阅读全文
posted @ 2009-05-20 10:41 redcoatjk 阅读(645) | 评论 (0)编辑 收藏
 
 

Java语言中, abstract class interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。abstract classinterface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进行抽象类定义时对于abstract classinterface的选择显得比较随意。其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析,试图给开发者提供一个在二者之间进行选择的依据。


理解抽象类

abstract class
interfaceJava语言中都是用来进行抽象类(本文 中的抽象类并非从abstract class翻译而来,它表示的是一个抽象体,而abstract classJava语言中用于定义抽象类的一种方法,请读者注意区分)定义的,那么什么是抽象类,使用抽象类能为我们带来什么好处呢?

面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。比如:如果我们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不同的,但是它们又都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能够实例化的。

在面向对象领域,抽象类主要用来进行类型隐藏。 我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。熟悉OCP的读者一定知道,为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle),抽象类是其中的关键所在。

从语法定义层面看abstract class interface

在语法层面,Java语言对于abstract classinterface给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。

使用abstract class的方式定义Demo抽象类的方式如下:
抽象类
abstract class Demo
abstract void method1();
abstract void method2();



使用interface的方式定义Demo抽象类的方式如下:
接口
interface Demo{
void method1();
void method2();

}


abstract class方式中,Demo可以有自己的数据成员,也可以有非 abstract的成员方法,(抽象类可以有非抽象的方法,有抽象方法的类一定要是抽象类)

 

而在interface方式的实现中,Demo只能够有静态不能被修改的数据成员(也就是必须是static final 的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract从某种意义上说,interface是一种特殊形式的 abstract class

从编程的角度来看,abstract classinterface都可以用来实现 "design by contract" 的思想。但是在具体的使用上面还是有一些区别的。
区别:
首先,abstract class Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系(因为Java不支持多继承 -- 转注)。但是,一个类却可以实现多个interface。也许,这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。 (即实现方式不同)

其次,在abstract class的定义中,我们可以赋予方法的默认行为。但是在interface的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会增加一些复杂性,有时会造成很大的麻烦。

抽象类中不能定义默认行为还存在另一个比较严重的问题,那就是可能会造成维护上的麻烦。因 为如果后来想修改类的界面(一般通过 abstract class 或者interface来表示)以适应新的情况(比如,添加新的方法或者给已用的方法中添加新的参数)时,就会非常的麻烦,可能要花费很多的时间(对于派生类很多的情况,尤为如此)。但是如果界面是通过abstract class来实现的,那 么可能就只需要修改定义在abstract class中的默认行为就可以了。

同样,如果不能在抽象类中定 义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了 "one ruleone place" 原则,造成代码重复,同样不利于以后的维护。因此,在abstract classinterface间进行选择时要非常的小心。

从设计理念层面看 abstract class interface

上面主要从语法定义和编程的角度论述了abstract classinterface的区别,这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面:abstract classinterface所反映出的设计理念,来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概念的本质所在。

前面已经提到过,abstract classJava语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is-a"关系,即父类和派生类在概念本质上应该是相同的。对于interface来说则不然,并不要求 interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。

考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作openclose,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:

使用abstract class方式定义Door

abstract class Door{
abstract void open();
abstract void close()

}

使用interface方式定义Door

interface Door{
void open();
void close();
}

其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract classinterface没有大的区别。

如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中, 主要是为了展示 abstract class interface 反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)?下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。

解决方案一:

简单的在Door的定义中增加一个alarm方法,如下:

abstract class Door{
abstract void open();
abstract void close()

abstract void alarm();
}

或者

interface Door{
void open();
void close();
void alarm();
}

那么具有报警功能的AlarmDoor的定义方式如下:

class AlarmDoor extends Door{
void open(){…}
void close(){…}
void alarm(){…}
}

或者

class AlarmDoor implements Door

void open(){…}
void close(){…}
void alarm(){…}


这种方法违反了面向对象设计中的一个核心原则 ISP (Interface Segregation Principle),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。

解决方案二:

既然openclosealarm属于两个不同的概念,根据ISP原则应该把它们分别 定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用 abstract class 方式定义;两个概念都使用interface方式定义;一个概念 使用 abstract class 方式定义,另一个概念使用interface方式定义。

显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。

如果两个概念都使用interface方式来定义,那么就反映出两个问题:1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用 interface方式定义)反映不出上述含义。

如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它 有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract classJava语言中表示一种继承关系,而继承关系 在本质上是"is-a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:

abstract class Door{
abstract void open();
abstract void close()

}
interface Alarm{
void alarm();
}
class Alarm Door extends Door implements Alarm{
void open(){…}
void close(){…}
void alarm(){…}
}

这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。 abstract class表示的是"is-a"关系,interface表示的是"like-a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。

小结

1.abstract class
Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface

2.
abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法.

interface中,只能够有静态的不能被修改的数据成员(也就是必须是 static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的。

3.abstract classinterface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。

4.
实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法接口中则不能有实现方法。

5.
接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

6.
抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

7.
接口中的方法默认都是 public,abstract 类型的

结论

abstract class
interface Java语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系(虽然都能够实现需求的功能)。这其实也是语言的一种的惯用法,希望读者朋友能够细细体会。

 

---

  补充一个: 接口可以extends接口 这个称之为接口的扩充

posted @ 2009-05-19 09:55 redcoatjk 阅读(115) | 评论 (0)编辑 收藏
 
Java 5 添加了许多强大的语言特性:泛型、枚举、注释、自动装箱和增强的 for 循环。但是,许多工作组仍然被绑定在 JDK 1.4 或以前的版本上,可能需要花些时间才能使用新版本。但是,这些开发人员仍然可以使用这些功能强大的语言特性,同时在 JVM 早期版本上部署。

  随着最新的 Java 6.0 的发布,您可能认为 Java 5 的语言特性是 “旧的新特性”。但是即使在现在,当我询问开发人员在开发时使用的 Java 平台的版本时,通常只有一半人在使用 Java 5 —— 另一半则只能表示羡慕。他们非常希望使用 Java 5 中添加的语言特性,例如泛型和注释,但仍有许多因素妨碍他们这样做。

  不能利用 Java 5 特性的开发人员包括那些开发组件、库或应用程序框架的开发人员。因为他们的客户可能仍然在使用 JDK 1.4 或以前的版本,并且 JDK 1.4 或以前的 JVM 不能装载用 Java 5 编译的类,所以使用 Java 5 语言特性会把他们的客户基数限制在已经迁移到 Java 5 的公司。

  另一类经常避免使用 Java 5 的开发人员是使用 Java EE 的开发人员。许多开发团队不愿在 Java EE 1.4 及以前的版本上使用 Java 5,因为担心其应用服务器的厂商不支持 Java 5。这些开发人员要迁移到 Java EE 5 可能还有待时日。除了 Java EE 5 和 Java SE 5 规范之间的滞后,商业 Java EE 5 容器没有必要在规范刚刚制定好就能使用,企业也没有必要在应用服务器出现下一个版本时就立即升级,而且在升级应用服务器之后,可能还需要花些时间在新平台上验证其应用程序。

  Java 5 语言特性的实现

  Java 5 中添加的语言特性 —— 泛型、枚举、注释、自动装箱和增强的 for 循环 —— 不需要修改 JVM 的指令集,几乎全部是在静态编译器(javac)和类库中实现的。当编译器遇到使用泛型的情况时,会试图检查是否保证了类型安全(如果不能检查,会发出 “unchecked cast”),然后发出字节码,生成的字节码与等价的非泛型代码、类型强制转换所生成的字节码相同。类似的,自动装箱和增强的 for 循环仅仅是等价的 “语法糖”,只是更复杂的语法和枚举被编译到普通的类中。

  在理论上,可以采用 javac 生成的类文件,在早期的 JVM 中装入它们,这实际上正是 JSR 14(负责泛型的 Java Community Process 工作组)的成立目的。但是,其他问题(例如注释的保持)迫使类文件的版本在 Java 1.4 和 Java 5 之间变化,因此妨碍了早期 JVM 中装入用 Java 5 编译的代码。而且,在 Java 5 中添加的有些语言特性依赖于 Java 5 库。如果用 javac -target 1.5 编译类,并试图将它装入早期 JVM 中,就会得到 UnsupportedClassVersionError,因为 -target 1.5 选项生成的类的类文件版本是 49,而 JDK 1.4 只支持版最大为 48 的类文件版本。

  for-each 循环

  增强的 for 循环有时叫做 for-each 循环,编译器编译它的时候,情形与程序员提供旧式 for 循环一样。for-each 循环能够迭代数组或集合中的元素。清单 1 显示了用 for-each 在集合上迭代的语法:

  清单 1. for-each 循环

  Collection fooCollection = ...
  for (Foo f : fooCollection) {
  doSomething(f);
  }

  编译器把这个代码转换成等价的基于迭代器的循环,如清单 2 所示:

  清单 2. 清单 1 基于迭代器的等价循环

  for (Iterator iter=f.iterator(); f.hasNext();) {
  Foo f = iter.next();
  doSomething(f);
  }

  编译器如何知道提供的参数有一个 iterator() 方法呢? javac 编译器的设计者可能已经内置了对集合框架的理解,但是这种方法有些不必要的限制。所以,创建了一个新的接口 java.lang.Iterable(请参阅清单 3 ),并翻新集合类使其实现 Iterable 接口。这样,不是在核心集合框架上构建的容器类也能利用新的 for-each 循环。但是这样做会形成对 Java 5 类库的依赖,因为在 JDK 1.4 中没有 Iterable。

  清单 3. Iterable 接口

  public interface Iterable {
  Iterator iterator();
  }

枚举和自动装箱

  正像 for-each 循环一样,枚举也要求来自类库的支持。当编译器遇到枚举类型时,生成的类将扩展库类 java.lang.Enum。但是,同 Iterable 一样,在 JDK 1.4 类库中也没有 Enum 类。

  类似的,自动装箱依赖于添加到原始包装器类(例如 Integer)的 valueOf() 方法。当装箱需要从 int 转换到 Integer 时,编译器并不调用 new Integer(int),而是生成对 Integer.valueOf(int) 的调用。valueOf() 方法的实现利用 享元(flyweight)模式 为常用的整数值缓存 Integer 对象(Java 6 的实现缓存从 -128 到 127 的整数),由于消除了冗余的实例化,可能会提高性能。而且,就像 Iterable 和 Enum 一样,valueOf() 方法在 JDK 1.4 类库中也不存在。

  变长参数

  当编译器遇到用变长参数列表定义的方法时,会把其转换成包含正确组件类型数组的方法;当编译器遇到带有变长参数列表方法的调用时,就把参数装进数组。

  注释

  定义了注释的之后,可以用 @Retention 对它进行注释,它可以决定编译器对使用这个注释的类、方法或字段执行什么处理。已经定义的保持策略有 SOURCE (在编译时舍弃注释数据)、CLASS (在类文件中记录注释)或 RUNTIME (在类文件中记录注释,并在运行时保留注释,这样就可以反射地访问它们了)。

  其他的库依赖关系

  在 Java 5 之前,当编译器遇到尝试连接两个字符串的情况时,会使用帮助器类 StringBuffer 执行连接。在 Java 5 及以后的版本中,转而调用新的 StringBuilder 类,JDK 1.4 及以前的类库中不存在该类。

  访问 Java 5 特性

  因为语言特性对库支持的依赖,即使使用 Java 5 编译器生成的类文件能够装入早期 JVM 版本,执行也会因为类装入错误而失败。但是,通过对字节码进行适当转换,仍有可能解决这些问题,因为这些遗漏的类并不包含实际的新功能。

  JSR 14

  在 Java 泛型规范(以及其他 Java 5 新添加的语言特性)的开发期间,在 javac 编译器中添加了试验性的支持,以便让它能使用 Java 5 的语言特性,并生成能在 Java 1.4 JVM 上运行的字节码。虽然这些特性不受支持(甚至是文档),但许多开源项目都使用了它们,使得开发人员能使用 Java 5 语言特性编码,并生成能在早期 JVM 上使用的 JAR 文件。而且,既然 javac 是开源的,那么这个特性有可能得到第三方的支持。要激活这些特性,可以用 -source 1.5 和 -target jsr14 选项调用 javac。

  javac 的 JSR 14 目标模式使编译器生成与 Java 5 语言特性对应的 JDK 1.4 兼容字节码:

  •   泛型和变长参数:编译器在泛型出现的地方插入的强制转换不依赖类库,所以能够在 Java 5 之前的 JVM 上很好地执行。类似的,编译器在出现变长参数列表的地方生成的代码也不依赖类库。
  •   for-each 循环:当迭代数组时,编译器生成归纳变量和标准的数组迭代语法。当在 Collection 上迭代时,编译器生成标准的基于迭代器的语法。当在非集合的 Iterable 上迭代时,编译器生成错误。
  •   自动装箱:编译器不生成对包装器类的 valueOf() 方法的调用,而是生成对构造函数的调用。
  •   字符串连接:javac 的 JSR 14 目标模式使编译器生成对 StringBuffer 的调用而不是对 StringBuilder 的调用。
  •   枚举:javac JSR 14 目标模式对枚举没有特殊支持。尝试使用枚举的代码会失败,在寻找 java.lang.Enum 基类时出现 NoClassDefFoundError。

  使用 JSR 14 目标模式允许在 “简易” 情况下编写使用泛型、自动装箱和 for-each 循环的代码,这对多数项目来说可能足够了。这很方便,如果不支持的话,编译器会一次生成基本兼容的字节码。

posted @ 2009-05-19 09:14 redcoatjk 阅读(320) | 评论 (0)编辑 收藏
 
JDK5新特性汇总(与1.4对照)
 

1 循环
5.0
1.4
for (type variable : array){
   body
}
 
for (int i = 0; i < array.length; i++){
   type variable = array[i];
   body
}
for (type variable : arrayList){
   body
}
for (int i = 0; i < arrayList.size(); i++){
   type variable = (type) arrayList.get(i);
   body
}
 
2 泛型
以ArrayList为例,包括创建一个容器对象和取得容器内对象操作:
5.0
1.4
ArrayList arrayList =
      new ArrayList()
ArrayList arrayList =
      new ArrayList();
arrayList.get(i)
(Type) arrayList.get(i)
 
3 自动装箱拆箱
在JDK5.0以前,在原始类型与相应的包装类之间的转化是不能自动完成的。要完成这种转化,需要手动调用包装类的构造函数:
5.0
1.4
Integer wrapper = n;
Integer wrapper = new Integer(n);
 
在JDK5.0环境中,可以自动转化,不再需要手工干预:
5.0
1.4
int n = wrapper;
int n = wrapper.intValue();
 
4 可变参数列表
5.0
1.4
method(other params, p1, p2, p3)
method(other params, new Type[] { p1, p2, p3 })
 
5 可变的返回类型
在JDK5.0以前,当覆盖父类方法时,返回类型是不能改变的。现在有新的规则用于覆盖方法。如下,一个典型的例子就是clone()方法:
5.0
1.4
public Employee clone() { ... }
...
Employee cloned = e.clone();
 
public Object clone() { ... }
...
Employee cloned = (Employee) e.clone();
 
 
 
 
 
 
 
6 静态导入
静态导入功能对于JDK 5.0以前的版本是不支持的。
5.0
1.4
import static java.lang.Math;
import static java.lang.System;
...
out.println(sqrt(PI));
 
System.out.println(Math.sqrt(Math.PI));
 
 
7 控制台输入
JDK 5.0先前的版本没有Scanner类,只能使用JOptionPane.showInputDialog类代替。
5.0
1.4
Scanner in = new Scanner(System.in);System.out.print(prompt);
int n = in.nextInt();
double x = in.nextDouble();
String s = in.nextLine();
String input = JOptionPane.showInputDialog(prompt);
int n = Integer.parseInt(input);
double x = Double.parseDouble(input);
s = input;
 
 
 
 
 
 
 
 
 
 
8 格式化输出
JDK5.0以前的版本没有print方法,只能使用NumberFormat.getNumberInstance来代替。
5.0
1.4
System.out.printf("%8.2f", x);
NumberFormat formatter
   = NumberFormat.getNumberInstance();
formatter.setMinimumFractionDigits(2);
formatter.setMaximumFractionDigits(2);
String formatted = formatter.format(x);
for (int i = formatted.length(); i < 8; i++)
   System.out.print(" "); System.out.print(formatted);
 
9 内容面板代理
在JDK5.0先前的版本中,JFrame,JDialog,JApplet等类没有代理add和setLayout方法。
5.0
1.4
add(component)
getContentPane().add(component)
setLayout(manager)
getContentPane().setLayout(manager)
 
10 StringBuilder类
JDK 5.0引入了StringBuilder类,这个类的方法不具有同步,这使得该类比StringBuffer类更高效。
5.0
1.4
StringBuilder
StringBuffer
posted @ 2009-05-19 08:58 redcoatjk 阅读(1099) | 评论 (2)编辑 收藏
 

摘自http://blog.ahnw.gov.cn/user1/itblog/archives/2007/8599.html
mal(numeric )             同义,用于精确存储数值

float 和 real                      不能精确存储数值


decimal 数据类型最多可存储 38 个数字,所有数字都能够放到小数点的右边。decimal 数据类型存储了一个准确(精确)的数字表达法;不存储值的近似值。

定义 decimal 的列、变量和参数的两种特性如下:

  • p   小数点左边和右边数字之和,不包括小数点。如 123.45,则 p=5,s=2。

    指定精度或对象能够控制的数字个数。

  • s

    指定可放到小数点右边的小数位数或数字个数。

    p 和 s 必须遵守以下规则:0 <= s <= p <= 38。

numericdecimal 数据类型的默认最大精度值是 38。在 Transact-SQL 中,numeric decimal 数据类型在功能上等效。

当数据值一定要按照指定精确存储时,可以用带有小数的 decimal 数据类型来存储数字。

float 和 real 数据

float real 数据类型被称为近似的数据类型。在近似数字数据类型方面,floatreal 数据的使用遵循 IEEE 754 标准。

近似数字数据类型并不存储为多数数字指定的精确值,它们只储存这些值的最近似值。在很多应用程序中,指定值与存储值之间的微小差异并不明显。但有时这些差异也值得引起注意。由于 floatreal 数据类型的这种近似性,当要求精确的数字状态时,比如在财务应用程序中,在那些需要舍入的操作中,或在等值核对的操作中,就不使用这些数据类型。这时就要用 integerdecimalmoneysmallmone 数据类型。

在 WHERE 子句搜索条件中(特别是 = 和 <> 运算符),应避免使用 floatreal 列。最好限制使用 floatreal 列做 > 或 < 的比较。

IEEE 754 规格提供了四种舍入模式:舍入到最接近的值、上舍入、下舍入和舍入到零。Microsoft® SQL Server™ 使用上舍入。所有的数值必须精确到确定的精度,但会产生细小的浮点值变化。因为浮点数字的二进制表示法可以采用很多合法舍入规则中的任意一条,因此我们不可能可靠地量化一个浮点值。

转换 decimal 和 numeric 数据

对于 decimal numeric 数据类型,Microsoft® SQL Server™ 将精度和小数位数的每个特定组合看作是不同的数据类型。例如,decimal(5,5) 和 decimal(5,0) 被当作不同的数据类型。

在 Transact-SQL 语句中,带有小数点的常量自动转换为 numeric 数据值,且必然使用最小的精度和小数位数。例如,常量 12.345 被转换为 numeric 值,其精度为 5,小数位为 3。

decimal numeric floatreal 转换会导致精度损失。从 intsmallinttinyintfloatrealmoney smallmoneydecimalnumeric 转换会导致溢出。

默认情况下,在将数字转换为较低精度和小数位数的 decimalnumeric 值时,SQL Server 使用舍入法。然而,如果 SET ARITHABORT 选项为 ON,当发生溢出时,SQL Server 会出现错误。若仅损失精度和小数位数,则不会产生错误.

posted @ 2009-05-18 15:21 redcoatjk 阅读(885) | 评论 (0)编辑 收藏
 

hql 多对多查询 elements

可编写如下Hql 语句完成查询:

Sql代码
  1.  
Sql代码 复制代码
  1. select Blog    
  2. from Blog, Book   
  3. where Blog.author in elements(Book.authors)   
  4.     and Book.id=?  


对应的Sql近似如下:

Sql代码
  1. select  blog.*   
  2. from  blog, book   
  3. where  (blog.author  in  ( select  author.authorid  
  4.         from  book_author   
  5.         where  book.id=book_author.bookid))   
  6.     and  book.id=? 
posted @ 2009-05-17 22:07 redcoatjk 阅读(534) | 评论 (0)编辑 收藏
 
摘自:http://blog.csdn.net/escode/archive/2008/11/04/3217052.aspx
本文中将讲述Hibernate的基本配置及配置文件的应用,这对于正确熟练使用Hibernate是相当关键的。

  配置文件中映射元素详解

  对象关系的映射是用一个XML文档来说明的。映射文档可以使用工具来生成,如XDoclet,Middlegen和AndroMDA等。下面从一个映射的例子开始讲解映射元素,映射文件的代码如下。

<?xml version="1.0"?>
<!--
所有的XML映射文件都需要定义如下所示的DOCTYPE。
Hibernate会先在它的类路径(classptah)中搜索DTD文件。

-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!--
hibernate-mapping有几个可选的属性:
schema属性指明了这个映射的表所在的schema名称。
default-cascade属性指定了默认的级联风格 可取值有 none、save、update。
auto-import属性默认让我们在查询语言中可以使用非全限定名的类名 可取值有 true、false。
package属性指定一个包前缀。
-->

<hibernate-mapping schema="schemaName" default-cascade="none"
auto-import="true" package="test">

<!--用class元素来定义一个持久化类 -->
<class name="People" table="person">
<!-- id元素定义了属性到数据库表主键字段的映射。-->
<id name="id">
<!-- 用来为该持久化类的实例生成唯一的标识 -->
<generator class="native"/>
</id>
<!-- discriminator识别器 是一种定义继承关系的映射方法-->

<discriminator column="subclass" type="character"/>
<!-- property元素为类声明了一个持久化的,JavaBean风格的属性-->
<property name="name" type="string">
<column name="name" length="64" not-null="true" />
</property>

<property name="sex"
not-null="true"
update="false"/>

<!--多对一映射关系-->
<many-to-one name="friend"
column="friend_id"
update="false"/>

<!--设置关联关系-->

<set name="friends" inverse="true" order-by="id">
<key column="friend_id"/>
<!—一对多映射-->
<one-to-many class="Cat"/>
</set>
</class>
</hibernate-mapping>

  组件应用的方法

  组件有两种类型,即组件(component)和动态组件(dynamic-component)。在配置文件中,component元素为子对象的元素与父类对应表的字段建立起映射关系。然后组件可以声明它们自己的属性、组件或者集合。component元素的定义如下所示:

<component name="propertyName" class="className" insert="true|false"
upate="true|false" access="field|property|ClassName">

<property ...../>
<many-to-one .... />
........
</component>

  在这段代码中,name是指属性名,class是类的名字,insert指的是被映射的字段是否出现在SQL的INSERT语句中,upate指出被映射的字段是否出现在SQL的UPDATE语句中,access指出访问属性的策略。
  Hiebernate的基本配置

  Hibernate的数据库连接信息是从配置文件中加载的。Hibernate 的配置文件有两种形式:一种是XML格式的文件,一种是properties属性文件。properties形式的配置文件默认文件名是 hibernate.properties,一个properties形式的配置文件内容如下所示:

#指定数据库使用的驱动类
hibernate.connection.driver_class = com.mysql.jdbc.Driver r

#指定数据库连接串
hibernate.connection.url = jdbc:mysql://localhost:3306/db


#指定数据库连接的用户名
hibernate.connection.username = user

#指定数据库连接的密码
hibernate.connection.password = password

#指定数据库使用的方言
hibernate.dialect = net.sf.hibernate.dialect.MySQLDialect

#指定是否打印SQL语句
hibernate.show_sql=true

  在配置文件中包含了一系列属性的配置,Hibernate将根据这些属性来连接数据库。

  在XML格式的配置文件中,除了基本的Hibernate配置信息,还可以指定具体的持久化类的映射文件,这可以避免将持久化类的配置文件硬编码在程序中。XML格式的配置文件的默认文件名为hibernate.cfg.xml,一个XML配置文件的示例如下所示:

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<!--显示执行的SQL语句-->
<property name="show_sql">true</property>

<!--连接字符串-->
<property name="connection.url">jdbc:mysql://localhost:3306/STU</property>

<!--连接数据库的用户名-->
<property name="connection.username">root</property>

<!--数据库用户密码-->
<property name="connection.password">root</property>

<!--数据库驱动-->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

<!--选择使用的方言-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

<!--映射文件 -->
<mapping resource="com/stuman/domain/Admin.hbm.xml" />

<!--映射文件-->
<mapping resource="com/stuman/domain/Student.hbm.xml" />

</session-factory>
</hibernate-configuration>

  properties形式的配置文件和XML格式的配置文件可以同时使用。当同时使用两种类型的配置文件时,XML配置文件中的设置会覆盖properties配置文件的相同的属性。

  对象标识符号

  在关系数据库表中,主键(Primary Key)用来识别记录,并保证每条记录的唯一性。在Java语言中,通过比较两个变量所引用对象的内存地址是否相同,或者比较两个变量引用的对象值是否相同来判断两对象是否相等。Hibernate为了解决两者之间的不同,使用对象标识符(OID)来标识对象的唯一性。OID是关系数据库中主键在Java 对象模型中的等价物。在运行时,Hibernate根据OID来维持Java对象和数据库表中记录的对应关系。如下代码所示,三次调用了Session的 load()方法,分别加载OID为1或3的User对象。

Transaction tx = session.beginTransaction();
User user1 = (User)session.load(User.class,new Long(1));
User user2 = (User)session.load(User.class,new Long(1));
User user3 = (User)session.load(User.class,new Long(3));
System.out.println( user1 == user2 );
System.out.println( user1 == user3 );

  应用程序在执行上述代码时,第一次加载OID为1的User对象,从数据库中查找ID为1的记录,然后创建相应的User实例,并把它保存在 Session缓存中,最后将该实例的引用赋值给变量user1。第二次加载OID为1的对象时,直接把Session缓存中OID为1的实例的引用赋值给变量user2。因此,表达式user1==user2的结果为true。

  标识的生成可以使用不同的策略,表1为Hibernate内置的标识生成策略。

  表1 Hibernate标识生成策略
标识符生成器
描述
increment 适用于代理主键。由Hibernate自动以递增方式生成。
identity 适用于代理主键。由底层数据库生成标识符。
sequence 适用于代理主键。Hibernate根据底层数据库的序列生成标识符,这要求底层数据库支持序列。
hilo 适用于代理主键。Hibernate分局high/low算法生成标识符。
seqhilo 适用于代理主键。使用一个高/低位算法来高效的生成long,short或者int类型的标识符。
native 适用于代理主键。根据底层数据库对自动生成标识符的方式,自动选择identity、sequence或hilo。
uuid.hex 适用于代理主键。Hibernate采用128位的UUID算法生成标识符。

uuid.string
适用于代理主键。UUID被编码成一个16字符长的字符串。
assigned 适用于自然主键。由Java应用程序负责生成标识符。
foreign 适用于代理主键。使用另外一个相关联的对象的标识符。
  Hibernate映射类型

  在对象/关系映射文件中,Hibernate采用映射类型作为Java类型和SQL类型的桥梁。Hibernate映射类型分为2种:内置映射类型和自定义映射类型。

  1、内置映射类型

  Hibernate对所有的Java原生类型、常用的Java类型如String、Date等都定义了内置的映射类型。表2列出了Hibernate映射类型、对应的Java类型以及对应的标准SQL类型。

  表2 Hibernate内置映射类型
Hibernate映射类型 Java类型 标准SQL类型 大小
integer/int java.lang.Integer/int INTEGER 4字节
long java.lang.Long/long BIGINT 8字节
short java.lang.Short/short SMALLINT 2字节
byte java.lang.Byte/byte TINYINT 1字节
float java.lang.Float/float FLOAT 4字节
double java.lang.Double/double DOUBLE 8字节
big_decimal java.math.BigDecimal NUMERIC  
character java.lang.Character/java.lang.String/char CHAR(1) 定长字符
string java.lang.String VARCHAR 变长字符
boolean/ yes_no/true_false java.lang.Boolean/Boolean BIT 布尔类型
date java.util.Date/java.sql.Date DATE 日期
timestamp java.util.Date/java.util.Timestamp TIMESTAMP 日期
calendar java.util.Calendar TIMESTAMP 日期
calendar_date java.util.Calendar DATE 日期
binary byte[] BLOB
BLOB
text java.lang.String TEXT CLOB
serializable 实现java.io.Serializablej接口的任意Java类 BLOB BLOB
clob java.sql.Clob CLOB CLOB
blob java.sql.Blob BLOB BLOB
class java.lang.Class VARCHAR 定长字符
locale java.util.Locale VARCHAR 定长字符
timezone java.util.TimeZone VARCHAR 定长字符
currency java.util.Currency VARCHAR 定长字符

  2、自定义映射类型

  Hibernate提供了自定义映射类型接口,允许用户以编程的方式创建自定义的映射类型。用户自定义的映射类型需要实现 net.sf.hibernate.UserType或net.sf.hibernate.CompositeUserType接口。具体的创建自定义映射类型的方法请参考hibernate官方文档或相关资料,这里不再详细介绍。
posted @ 2009-05-13 18:10 redcoatjk 阅读(538) | 评论 (0)编辑 收藏
 
Spring XML配置的12个技巧
Spring是一个强有力的java程序框架,其被广泛应用于java的程序中。它用POJO提供了企业级服务。Spring利用依赖注入可以获得简单而有效的测试能力。Spring beans,依赖关系,以及服务所需要的bean都将在配置文件中予以描述,配置文件一般采用XML格式。然而XML配置文件冗长而不易使用,在你进行一个使用了大量bean的大项目中它将变得难以阅读和控制。



在这篇文章中我将给你展示12种的有关Spring XML配置文件的最佳技巧。它们中的一些具有更多的实际意义,而不仅是最好的技巧。请注意另外一些因素,例如域模型的设计,会影响到XML配置,但是这篇文章更关注于XML配置的可读性和可操控性。



1. 避免使用自动装配

Spring可以通过bean类的自省来实现自动装配依赖,这样的话你就不必明确地描述bean的属性或者构造函数的参数。根据属性名称活匹配类型,bean属性可以自动进行装配。而构造函数可以根据匹配类型自动装配。你甚至可以设置自动装配进行自动侦测,这样Spring替你就会选择一个合适的机制。请看下面的例子:





Spring可以通过bean类的自省来实现自动装配依赖,这样的话你就不必明确地描述bean的属性或者构造函数的参数。根据属性名称活匹配类型,bean属性可以自动进行装配。而构造函数可以根据匹配类型自动装配。你甚至可以设置自动装配进行自动侦测,这样Spring替你就会选择一个合适的机制。请看下面的例子:



  <bean id="orderService"

    class="com.lizjason.spring.OrderService"

    autowire="byName"/>



OrderService类的属性名被用来和容器中的一个bean实例进行匹配。自动装配会默默的保存一些类型信息并降低混乱。然而,由于它会牺牲掉这种配置的直观性和可维护性,你在实际的项目中将不会用到它。许多指南和陈述材料都把它吹捧为Spring的一个非常cool的特性,而没有提到它的这个缺点。依我之见,就像Spring的对象池一样,它更多了一些商业味道。它看起来好像可以使XML配置文件更精简一些,但实际上却增加其复杂性,尤其是在你的较大规模的工程中已经定义了很多bean的时候更是如此。Spring允许你混合使用自动和手动装配,但是这种矛盾会使XML配置更加的令人费解。



2. 使用命名规范

和Java编码的理念一样,在项目中始终用清晰的,描述性的,一致的命名规范对开发人员理解XML配置非常有用。拿bean ID举例来说,你可以遵循Java类中属性的命名规范。比如说,OrderServiceDAO的bean ID应该是orderServiceDAO。对于大项目来说,在bean ID前加包名来作为前缀。



3. 使用简化格式

简化格式有利于减少冗余,因为它把属性值和引用作为属性,而不是子元素。看下面的例子:

  <bean id="orderService"     class="com.lizjason.spring.OrderService">     <property name="companyName">         <value>lizjason</value>     </property>     <constructor-arg>         <ref bean="orderDAO">     </constructor-arg>   </bean>以上程序可以重新以简化格式书写为:

  <bean id="orderService"     class="com.lizjason.spring.OrderService">     <property name="companyName"         value="lizjason"/>     <constructor-arg ref="orderDAO"/>   </bean>简化格式在1.2版本时已经可用了,但请注意不存在<ref local="...">这种简化格式不仅可以较少你的代码输入量,而且可以使XML配置更加的清晰。当你的配置文件中存在大量的bean定义时,它可以显著地提高可读性。



4. 尽量使用type而不是index去解决构造函数参数的匹配问题

当构造函数中有多个同类型的参数时,Spring只允许你使用从0开始的index或者value标签来解决这个问题。请看下面的例子:

  <bean id="billingService"     class="com.lizjason.spring.BillingService">     <constructor-arg index="0" value="lizjason"/>     <constructor-arg index="1" value="100"/>   </bean>最好用type属性取代上面的做法:

  <bean id="billingService"     class="com.lizjason.spring.BillingService">     <constructor-arg type="java.lang.String"         value="lizjason"/>     <constructor-arg type="int" value="100"/>   </bean>

用index可以稍微减少冗余,但是它更容易出错且不如type属性可读性高。你应该仅在构造函数中有参数冲突时使用index。



5. 如可能,尽量复用bean定义

Spring提供了一种类似于继承的机制来降低配置信息的重复并使XML配置更加的简单。一个子bean可以从它的父bean继承配置信息,本质上这个父bean就像它的子bean的一个模板。这是一个在大型项目中必须使用的特性。所有你要做的就是把父bean的abstract属性置为true,并在子bean中加以引用。例如:

  <bean id="abstractService" abstract="true"     class="com.lizjason.spring.AbstractService">     <property name="companyName"         value="lizjason"/>   </bean>   <bean id="shippingService"     parent="abstractService"     class="com.lizjason.spring.ShippingService">     <property name="shippedBy" value="lizjason"/>   </bean>shippingService bean继承了abstractService bean的属性companyName的值lizjason。注意,如果你为bean声名一个class或工厂方法,这个bean将会默认为abstract



6. 尽量使用ApplicationContext装配bean,而不是用import

像Ant脚本中imports一样,Spring的import 元素对于模块化bean的装配非常有用,例如:

  <beans>     <import resource="billingServices.xml"/>     <import resource="shippingServices.xml"/>     <bean id="orderService"         class="com.lizjason.spring.OrderService"/>   <beans>然而,比起在XML中用imports预装配这些bean,利用ApplicationContext来配置它们将更加灵活,也可以使XML配置更加的易于管理。你可以像下面这样传递一个bean定义数组到ApplicationContext的构造函数中:

  String[] serviceResources =

    {"orderServices.xml",

    "billingServices.xml",

    "shippingServices.xml"};

ApplicationContext orderServiceContext = new

ClassPathXmlApplicationContext(serviceResources);



7. 用id来标识bean

你可以用id或名字作为bean的标识。用id可读性较差,但是它可以影响XML分析器使bean的reference有效。如果id由于XML IDREF约束而无法使用,你可以用name作为bean的标识。XML IDREF约束是指id必须以字母开始(或者是在XML声名了的一个标点符号),后面可以是字母,数字,连字符,下划线,冒号或full stops(不知道怎么翻译好)。在实际应用中很少会遇到XML IDREF约束问题。



8. 在开发阶段使用依赖检查

你可以为bean的dependency-check属性设置一个值来取代默认的none,比如说simple,objects或者all,这样的话容器将替你做依赖有效性的检查。当一个bean的所有属性(或者某些属性目录)都被明确设置,或利用自动装配时将会非常有用。

  <bean id="orderService"     class="com.lizjason.spring.OrderService"     dependency-check="objects">     <property name="companyName"         value="lizjason"/>     <constructor-arg ref="orderDAO"/>   </bean>在这个例子中,容器将确保这些属性不是privitives或者保证collections是为orderService bean设置的。为所有的bean设置默认的依赖检查是可能的,但这个特性由于有些bean的属性不需要设置而很少使用。



9. 为每个配置文件加一个描述注释

在XML配置文件中最好使用有描述性的id和name,而不是成堆的注释。另外,加一个文件描述头将会非常有用,这个描述可以概括文件中定义的bean。另一个选择,你可以在description元素中加入描述信息。例如:

  <beans>     <description>         This file defines billing service         related beans and it depends on         baseServices.xml,which provides         service bean templates...     </description>     ...   </beans>用description元素的一个好处就是工具可以很容易的把描述信息从这个元素中提取出来。



10.   和team members沟通变更

当你修改java源码后,要确保更改了配置文件中的相应部分并把这个情况告知你的team members。XML配置文件也是代码,它们是程序的重要组成部分,但它们很难阅读和维护。大多数时间里,你需要同时看XML配置文件和java代码才能知道是怎么回事。



11.   setter注入和构造函数注入,优先使用前者

Spring提供了三种注入方式:构造函数注入,setter注入和方法注入。一般我们使用前两种。

  <bean id="orderService"     class="com.lizjason.spring.OrderService">     <constructor-arg ref="orderDAO"/>   </bean>   <bean id="billingService"     class="com.lizjason.spring.BillingService">     <property name="billingDAO"         ref="billingDAO">   </bean>在这个例子中,orderService bean用了构造函数注入,而BillingService bean用了setter注入。构造函数注入可以确保bean正确地构建,但是setter注入更加的灵活和易于控制,特别是当class有多个属性并且它们中的一些是可选的情况是更是如此。



12.   不要滥用注入

就像前面提到的,Spring的ApplicationContext可以替你创建java对象,但不是所有的java对象都应该通过注入创建。例如,域对象就不应该通过ApplicationContext创建。Spring是一个优秀的框架,但是考虑到可读性和可操控性,基于XML配置的配置会在定义很多bean的时候出现麻烦。过渡使用依赖注入将会使XML配置更加的复杂和冗长。切记,当使用高效的IDE时,例如Eclipse and IntelliJ,java代码更加的易于阅读,维护和管理比使XML文件



结论

XML是Spring流行的配置格式。存在大量bean定义时,基于XML的配置会变得冗长而不易使用。Spring提供了丰富的配置选项。适当地使用这些选项可以使XML配置更加的清晰,但其它的一些选项,例如自动装配,可能会降低可读性和可维护性。参考本文中提到的这些技巧可能会帮助你创建干净而易读的XML配置文件。
posted @ 2009-05-10 09:47 redcoatjk 阅读(143) | 评论 (0)编辑 收藏
 

1、如何将java.util.Date转化为java.sql.Date?
转化:

java.sql.Date sd;
java.util.Date ud;
//initialize the ud such as ud = new java.util.Date();

sd = new java.sql.Date(ud.getTime());

2、如果要插入到数据库并且相应的字段为Date类型
那么可以用PreparedStatement.setDate(int ,java.sql.Date)方法
其中的java.sql.Date可以用上面的方法得到

也可以用数据库提供TO_DATE函数
比如 现有 ud
TO_DATE(new SimpleDateFormat().format(ud,"yyyy-MM-dd HH:mm:ss"),
"YYYY-MM-DD HH24:MI:SS")
注意java中表示格式和数据库提供的格式的不同

一个实际的例子

sql="update tablename set timer=to_date('"+t+"','yyyymmddhh24miss') where ....."

这里的t为变量为类似:20051211131223

 

3、如何将"yyyy-mm-dd"格式的字符串转换为java.sql.Date

方法1

SimpleDateFormat bartDateFormat =  
        new SimpleDateFormat("yyyy-MM-dd");  
       String dateStringToParse = "2007-7-12";  
       try {  
        java.util.Date date = bartDateFormat.parse(dateStringToParse);  
        java.sql.Date sqlDate = new java.sql.Date(date.getTime());
        System.out.println(sqlDate.getTime());  
       }  
       catch (Exception ex) {  
        System.out.println(ex.getMessage());  
       }

------------------------------------------------------------
方法2
       String     strDate     =     "2002-08-09";   
       StringTokenizer     st     =     new     StringTokenizer(strDate,     "-");   
       java.sql.Date     date     =     new     java.sql.Date(Integer.parseInt(st.nextToken()),
                Integer.parseInt(st.nextToken()),
                 Integer.parseInt(st.nextToken()));

  
java.util.Date和java.sql.Date的异同
java.sql.Date,java.sql.Time和java.sql.Timestamp三个都是java.util.Date的子类(包装类)。

        但是为什么java.sql.Date类型的值插入到数据库中Date字段中会发生数据截取呢?

        java.sql.Date是为了配合SQL DATE而设置的数据类型。“规范化”的java.sql.Date只包含年月日信息,时分秒毫秒都会清零。格式类似:YYYY-MM-DD。当我们调用ResultSet的getDate()方法来获得返回值时,java程序会参照"规范"的java.sql.Date来格式化数据库中的数值。因此,如果数据库中存在的非规范化部分的信息将会被劫取。

        在sun提供的ResultSet.java中这样对getDate进行注释的:
       Retrieves the of the designated column in the current row of this <code>ResultSet</code> object as a “java.sql.Date” object in the Java programming language.

         同理。如果我们把一个java.sql.Date值通过PrepareStatement的setDate方法存入数据库时,java程序会对传入的java.sql.Date规范化,非规范化的部分将会被劫取。然而,我们java.sql.Date一般由java.util.Date转换过来,如:java.sql.Date sqlDate=new java.sql.Date(new java.util.Date().getTime()).
显然,这样转换过来的java.sql.Date往往不是一个规范的java.sql.Date.要保存java.util.Date的精确值,
我们需要利用java.sql.Timestamp.
Calendar

Calendar   calendar=Calendar.getInstance();  
//获得当前时间,声明时间变量  
int   year=calendar.get(Calendar.YEAR);  
//得到年
int   month=calendar.get(Calendar.MONTH);  
//得到月,但是,月份要加上1  
month=month+1;
int   date=calendar.get(Calendar.DATE);  
//获得日期  
String   today=""+year+"-"+month+"-"+date+"";



java.util.Date 就是在除了SQL语句的情况下面使用
java.sql.Date 是针对SQL语句使用的,它只包含日期而没有时间部分
它都有getTime方法返回毫秒数,自然就可以直接构建
java.util.Date d = new java.util.Date(sqlDate.getTime());
...

 


 


java.util.Date 是 java.sql.Date 的父类(注意拼写)
前者是常用的表示时间的类,我们通常格式化或者得到当前时间都是用他
后者之后在读写数据库的时候用他,因为PreparedStament的setDate()的第2参数和ResultSet的getDate()方法的第2个参数都是java.sql.Date 
转换是
java.sql.Date date=new Java.sql.Date();
java.util.Date d=new java.util.Date (date.getTime());
反过来是一样的

 


 


同意 jFresH_MaN

 


 


继承关系:java.lang.Object  --》  java.util.Date --》 java.sql.Date
具体的转换关系就是java.util.Date d=new java.util.Date (new Java.sql.Date());

 


 


sql.date,一般是在数据库的时间字段,util.date一般是日常日期字段

 


 


java.sql.Date主要是用于sql中的!
而java.util.Date用语一般的环境下都行!

 


 

SimpleDateFormat f=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
       java.util.Date utilDate=new Date();      
       java.sql.Date sqlDate=new java.sql.Date(utilDate.getTime());  
      
       java.sql.Time sTime=new java.sql.Time(utilDate.getTime());
      
      
      
       java.sql.Timestamp stp=new java.sql.Timestamp(utilDate.getTime());
            
      
       System.out.println(utilDate.getYear());

这里所有时间日期都可以被SimpleDateFormat格式化format()

f.format(stp);f.format(sTime);f.format(sqlDate);f.format(utilDate)

 

java.sql.Date sqlDate=java.sql.Date.valueOf("2005-12-12");
      
       utilDate=new java.util.Date(sqlDate.getTime());

 

--------------------------------------------------------------------------------------------------

另类取得年月日的方法:

import java.text.SimpleDateFormat;import java.util.*;java.util.Date date = new java.util.Date();//如果希望得到YYYYMMDD的格式SimpleDateFormat sy1=new SimpleDateFormat("yyyyMMDD");String dateFormat=sy1.format(date);//如果希望分开得到年,月,日SimpleDateFormat sy=new SimpleDateFormat("yyyy");SimpleDateFormat sm=new SimpleDateFormat("MM");SimpleDateFormat sd=new SimpleDateFormat("dd");String syear=sy.format(date);String smon=sm.format(date);String sday=sd.format(date);

 


      



Trackback: http://tb.donews.net/TrackBack.aspx?PostId=463449

posted @ 2009-05-08 16:59 redcoatjk 阅读(3199) | 评论 (0)编辑 收藏
 
ERP、OA、MIS、CRM、BI等等都是什么 引用:http://www.zuoyefeng.com/html/2006-12/484.htm -------------------------------------------------------------------------------- ERP -------------------------------------------------------------------------------- ERP是指英文Enterprise Resource Planning(企业资源计划)的简写 本着整体规划,分步实施的原则,对ERP项目所有方面的计划、组织、管理和监控,是为了达到项目实施后的预期成果和目标而采取内部和外部的持续性的工作程序。这是对时间、成本,以及产品、服务细节的需求相互间可能发生矛盾进行平衡的基本原则。建立起一整套行之有效的项目和风险管理机制,对提高ERP系统的实施成功率至关重要。 ERP项目管理相关背景(ERP History of Project Management) 既然ERP是企业管理信息系统,实施应用必然要结合业务流程的优化,也就是企业资源配置的合理化,而企业的效益又依赖于描述这种配置规划模型的优化,那么就让我们把建立规划模型的优化作为我们首要的同时也是最终的目标,其他任务都放在次要的从属地位上。在ERP的实施中,要把ERP与工业自动控制系统的概念分开。ERP是一个资源调度或决策支持系统,其中有对生产、设备、能力及各种工艺的评估和计算,但不能等同于自动控制。的评估和计算,但不能等同于自动控制。 OA -------------------------------------------------------------------------------- OA是OFFICE AUTOMATION的缩写,本意为利用技术的手段提高办公的效率,进而实现办公的自动化处理。 采用Internet/Intranet技术,基于工作流的概念,使企业内部人员方便快捷地共享信息,高效地协同工作;改变过去复杂、低效的手工办公方式,实现迅速、全方位的信息采集、信息处理,为企业的管理和决策提供科学的依据。一个企业实现办公自动化的程度也是衡量其实现现代化管理的标准。OA从最初的以大规模采用复印机等办公设备为标志的初级阶段,发展到今天的以运用网络和计算机为标志的现阶段,对企业办公方式的改变和效率的提高起到了积极的促进作用 CRM -------------------------------------------------------------------------------- CRM是customer relationship management(客户关系管理)的缩写,它是一项综合的IT技术,也是一种新的运作模式,它源于“以客户为中心”的新型商业模式,是一种旨在改善企业与客户关系的新型管理机制。通过向企业的销售、市场、服务等部门和人员提供全面及个性化的客户资料,并强化跟踪服务、信息分析能力,使他们能够协同建立和维护一系列与客户以及商业伙伴之间卓有成效的“一对一关系”,从而使企业得以提供更快捷和周到的优质服务,提高客户满意度,吸引和保持更多的客户,从而增加营业额,并通过信息共享和优化商业流程有效地降低企业经营成本。通俗地说,CRM就是利用软件、硬件和网络技术,为企业建立一个客户信息收集、管理、分析、利用的信息系统。 客户关系管理的功能主要分为四大部分: 1.客户信息管理 整合记录企业各部门、每个人所接触的客户资料进行统一管理,这包括对客户类型的划分、客户基本信息、客户联系人信息、企业销售人员的跟踪记录、客户状态、合同信息等。 2.市场营销管理 制订市场推广计划,并对各种渠道(包括传统营销、电话营销、网上营销)接触客户进行记录、分类和辨识,提供对潜在客户的管理,并对各种市场活动的成效进行评价。CRM营销管理最重要的是实现1 for 1营销,从“宏营销”到“微营销”的转变。 3.销售管理 功能包括对销售人员电话销售、现场销售、销售佣金等管理,支持现场销售人员的移动通信设备或掌上电脑接入。进一步扩展的功能还包括帮助企业建立网上商店、支持网上结算管理及与物流软件系统的接口。 4.服务管理与客户关怀 功能包括产品安装档案、服务请求、服务内容、服务网点、服务收费等管理信息,详细记录服务全程进行情况。支持现场服务与自助服务,辅助支持实现客户关怀。 MIS -------------------------------------------------------------------------------- MIS(管理信息系统--Management Information System)系统 ,是一个由人、计算机及其他外围设备等 组成的能进行信息的收集、传递、存贮、加工、维护和使用的系统。它是一门新兴的科学,其主要任务是最大限度的利用现代计算机及网络通讯技术加强企业的信息管理,通过对企业拥有的人力、物力、财力、设备、技术等资源的调查了解,建立正确的数据,加工处理并编制成各种信息资料及时提供给管理人员,以便进行正确的决策,不断提高企业的管理水平和经济效益。目前,企业的计算机网络已成为企业进行技术改造及提高企业管理水平的重要手段。随着我国与世界信息高速公路的接轨,企业通过计算机网络获得信息必将为企业带来巨大的经济效益和社会效益,企业的办公及管理都将朝着高效、快速、无纸化的方向发展。MIS系统通常用于系统决策,例如,可以利用MIS系统找出目前迫切需要解决的问题,并将信息及时反馈给上层管理人员,使他们了解当前工作发展的进展或不足。换句话说,MIS系统的最终目的是使管理人员及时了解公司现状,把握将来的发展路径。 一个完整的MIS应包括:辅助决策系统(DSS)、工业控制系统(IPC)、办公自动化系统(OA)以及数据库、模型库、方法库、知识库和与上级机关及外界交换信息的接口。其中,特别是办公自动化系统(OA)、与上级机关及外界交换信息等都离不开Intranet的应用。可以这样说,现代企业MIS不能没有Intranet,但Intranet的建立又必须依赖于MIS的体系结构和软硬件环境。 传统的MIS系统的核心是CS(Client/Server——客户端/服务器)架构,而基于Internet的MIS系统的核心是BS(Browser/Server——浏览器/服务器)架构。BS架构比起CS架构有着很大的优越性,传统的MIS系统依赖于专门的操作环境,这意味着操作者的活动空间受到极大限制;而BS架构则不需要专门的操作环境,在任何地方,只要能上网,就能够操作MIS系统,这其中的优劣差别是不言而喻的。 基于Internet上的MIS系统是对传统MIS系统概念上的扩展,它不仅可以用于高层决策,而且可以用于进行普通的商务管理。通过用户的具名登录(或匿名登录),以及相应的权限控制,可以实现在远端对系统的浏览、查询、控制和审阅。随着Internet的扩展,现有的公司和学校不再局限于物理的有形的真实的地域,网络本身成为事实上发展的空间。基于Internet上的MIS系统,弥补了传统MIS系统的不足,充分体现了现代网络时代的特点。随着Internet技术的高速发展,因特网必将成为人类新社会的技术基石。基于Internet的MIS系统必将成为网络时代的新一代管理信息系统,前景极为乐观。 BI -------------------------------------------------------------------------------- Business Intelligence(BI) 商务智能 IDC将商业智能定义为下列软件工具的集合: 1.终端用户查询和报告工具。专门用来支持初级用户的原始数据访问,不包括适用于专业人士的成品报告生成工具 2.OLAP工具。提供多维数据管理环境,其典型的应用是对商业问题的建模与商业数据分析。OLAP也被称为多维分析 3.数据挖掘(Data Mining)软件。使用诸如神经网络、规则归纳等技术,用来发现数据之间的关系,做出基于数据的推断。 4.数据集市(Data Mart)和数据仓库(Data Warehouse)产品。包括数据转换、管理和存取等方面的预配置软件,通常还包括一些业务模型,如财务分析模型。 5.主管信息系统(EIS,Executive Information System) 这个定义应该是比较学术了,客户多半不明白。 其实BI通俗来讲就是收集相关信息并加以分析,以帮助您做决策。成功的BI系统多采用了数据仓库技术。 Rose -------------------------------------------------------------------------------- 强大的面向对象的可视化分析、设计、建模工具;      Rational Rose支持各类可视化建模,诸如系统需求、事务进程、企业商务对象、及软件组件、软件结构、软件对象的 可视化建模等。Rational Rose 支持统一建模语言(UML),UML是对软件组件及其交互作用进行可视化建模的工业标准,已经得到了Microsoft,Oracle,Hewlett-Packard,Texas Instruments和MC I Systemhouse等众多公司的正式认可。       Rational Rose可以和任何一种面向对象应用程序结构组合使用。循环迭代开发 ---包括源代码生成的正向工程和已存在代码返回到图形对象模型的逆向工程--- 通过Rational Rose系列产品得到各类主要编程语言和快速应用开发工具的直接支持。       关键效益 *提高沟通能力。 团队所有人员使用同一语言,避免了在术语及需求上的混乱。由于设计人员和实施人员的准确沟通,使得计划和编程的过渡时间缩短,减少了错误的发生。 *可管理的复杂性。 有着大量变数的复杂系统可以很容易的被理解。设计人员可以集中进行大图的设计,而不是更小的细节。这样的结果是开发的时间缩短了,所建的系统是逻辑型和流线型的。 *详细的软件结构。 能创建出软件设计的蓝图,需求及变量被清楚的定义。这样的结果是在设计过程中有更少的错误发生,所创造的系统更强大更具弹性。 *重用。 创建应用设计的可控单元,只需改变模型或部分模型,无需改变整个应用,就可以改变或更新项目。这样既省时又提高了生产率。 *获取商务进程。 系统的需求在Use Case中抓取,从用户的角度来定义商务进程。定义进程是用文本格式来,而不是用计算机术语。这样,一个流畅的开发进程就创建出来了,因为从一开始所有的需求就十分明确,所以最终产品也能满足最终用户的需求
posted @ 2009-05-03 10:19 redcoatjk 阅读(200) | 评论 (0)编辑 收藏
仅列出标题
共8页: 上一页 1 2 3 4 5 6 7 8 下一页 
CALENDER
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(3)

随笔分类(22)

随笔档案(76)

文章分类(12)

文章档案(17)

搜索

  •  

积分与排名

  • 积分 - 249961
  • 排名 - 227

最新评论

评论排行榜


Powered By: 博客园
模板提供沪江博客