隨筆:93 文章:11 評論:22 引用:0
          首頁 發新隨筆
          發新文章 聯系 聚合管理

               摘要:   Java接口和Java抽象類     在沒有好好地研習面向對象設計的設計模式之前,我對Java接口和Java抽象類的認識還是很模糊,很不可理解。         剛學Java語言時,就很難理解為什么要有接口這個概念,雖說是可以實現所謂的多繼承,可一個只有方法名,沒有方法體的東西,...  閱讀全文
          posted @ 2009-05-20 10:41 redcoatjk 閱讀(658) | 評論 (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 閱讀(121) | 評論 (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 閱讀(331) | 評論 (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 閱讀(1109) | 評論 (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 閱讀(891) | 評論 (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 閱讀(538) | 評論 (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 閱讀(543) | 評論 (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 閱讀(147) | 評論 (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 閱讀(3205) | 評論 (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 閱讀(210) | 評論 (0)編輯 收藏
          僅列出標題
          共8頁: 上一頁 1 2 3 4 5 6 7 8 下一頁 
          CALENDER
          <2025年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          常用鏈接

          留言簿(3)

          隨筆分類(22)

          隨筆檔案(76)

          文章分類(12)

          文章檔案(17)

          搜索

          •  

          積分與排名

          • 積分 - 251122
          • 排名 - 227

          最新評論

          評論排行榜


          Powered By: 博客園
          模板提供滬江博客

          主站蜘蛛池模板: 岳池县| 道孚县| 武城县| 齐齐哈尔市| 高唐县| 九江市| 隆昌县| 全南县| 灵川县| 东丽区| 渑池县| 宁晋县| 桃源县| 离岛区| 英超| 五华县| 大埔区| 平昌县| 南投市| 阿坝| 承德市| 普兰店市| 福州市| 无棣县| 新津县| 揭阳市| 安庆市| 芜湖县| 深泽县| 孟津县| 彭阳县| 泸溪县| 遂昌县| 昌吉市| 金华市| 南昌市| 陇南市| 庄河市| 蒙自县| 苏尼特左旗| 山东|