2015年6月25日 星期四

Hibernate3.x的Hello World (使用Hibernate tools)(Hibernate3.x一)

Hibernate3.xHello World
maven創一個空專案後,去http://mvnrepository.com,將hibernatejavassistdependency貼到pom.xml裡,如果不下載javassist執行會有錯誤提示,還有資料庫的驅動程式也要加



設定好後,寫一個對應DBjava bean

以下分兩個部分,XML設定和Annotation設定

XML設定
Add Class,然後選剛剛新建的java bean

會自動生成xml,看以下講解,有不對的在修改一下就可以了,class name裡面的路徑可以按Ctrl鍵,然後滑鼠移過去,有出現底線表示有連成功

設定完後要讓hibernate.cfg.xml知道,所以要下<mapping resource>,一樣用Ctrl去偵測看看有沒有連成功

寫測試類,configure()裡面,可以設指定的路徑去讀xml,也就是不一定要叫hibernate.cfg.xml
hbm.xml有個<generator>,如果要變成流水號的形式
oracle可以這樣用
<generator class="sequence">
<param name="sequence">SEQ_HIBERNATE_USERS</param>
</generator>
SEQ_HIBERNATE_USERS這些字是因為DB的設定

CREATE SEQUENCE SEQ_HIBERNATE_USERS
    INCREMENT BY 10  -- 每次加幾個
    START WITH 10        -- 從10開始計數
    NOMAXVALUE        -- 不設置最大值
    NOCYCLE                  -- 一直累加,不循環
    CACHE 10;
所以我們要取得流水號才會用SEQ_HIBERNATE_USERS.NEXTVAL或SEQ_HIBERNATE_USERS.CURRVAL
其他DB和方法可以參考這裡Hibernate标识符属性(主键)生成策略全析

雖然Oracle12c有支援自增主鍵了(看這篇的最下面),但使用Hibernate時,我給identity,還是出現不支援的錯誤,但我只試 3.6.10 版



Annotation設定

因為是annotation設定,所以不用hbm.xml
但也是要讓hibernate.cfg.xml知道,所以要設<mapping class>,剛剛的xml設定是<mapping resource>,不要搞錯了,設完後,一樣用Ctrl測試

Java bean 如下設定,注意@開頭的都是javax.persistence.*裡面,不是hibernate的喔!
@Entity表示可以連到DB的類
@IDDB主鍵
@ColumnDB的欄位
要完全和DB的欄位一模一樣才可以
annotation也可以寫在setter/getter上面

DB常常有底線,所以java連不到,所以還可以這樣寫
@GeneratedValue是設定流水號之類用的

這樣子java的屬性就可以亂打了,但唯一就是@Id,沒有name可以設定,我目前也沒找到其他方法,所以目前就Id先和DB的欄位名稱一樣,其他隨便,測試類和XML設定一樣

值得一提的就是,如果使用hbm.xml,而且annotation也寫了,而且還亂寫,還是能執行成功,感覺應該是annotation沒作用而已

 ※用功具生成class

剛剛打的persistent class 打得太累了,所以有個工具專門做這件事的,首先要有一個console,然後reverse轉換,最後Generation,三合一的

※新增一個Hibernate Console設定






Console的名稱,預設為專案名稱,選對應的版本,然後專案名稱,還有資料庫連線,及設定檔的位置,大部分都自動長出來了






設定完後,用這個路徑打開看一下





注意要按下Database的三角形,能出現table名稱,才表示ok






這邊我卡超久的,按下Database的三角形後,出現Pending…,等到我都拉完屎了,它還在Pending…,最後還錯誤。我來我發現,在cfg.xml多設定一個叫hibernate.default_schema,就可以了,一定要大寫,不然什麼都沒有

※TABLE SCHEMA:

指Table有關欄位名稱、長度、約束條件、主鍵.....等等有關Table的資訊

※SCHEMA:
可以把Database看作是一個大倉庫,倉庫分了很多很多的房間,Schema就是其中的房間,一個Schema代表一個房間,Table可以看作是每個Schema中的床,Table(床)就被放入每個房間中。
然後床上可以放置很多物品,就好比Table上可以放置很多列和行一樣,數據庫中存儲數據的基本單元是Table,現實中每個倉庫放置物品的基本單位就是床, User就是每個Schema的主人(所以Schema包含的是Object,而不是User)。

一個用戶一般對應一個schema,該用戶的schema名等於用戶名,並作為該用戶預設schema。這也就是在企業管理器的方案下看到schema名都為資料庫用戶名的原因。






※新增Hibernate Reverse Engineering File


問你生成的reveng.xml要放哪,就放src下好了


先選Console configuration裡剛剛設定好的console,然後Refresh,左邊就會出現資料庫的table,選要轉換的table後按Include,讓它到右邊後完成
 
經過辛苦的設定後,想不到內容這麼少



Hibernate Code Generation設定
Open Perspective,不是Show View
Hibernate可以選



這樣以後就有Hibernate(右圖)的圖,不用在Open Perspective了,要切回去時,只要按Java EE圖示即可。
選這個專用的圖示(左圖),我之前因為不知道Open Perspective,所以找不到這個圖示,好可怕




左邊先選最下面的框,才能選上面的「+」圖示,右邊的Name,給個名字,通常是專案名稱加_configurationreveng.xml選已存在的





選剛剛建立的reveng.xml






切換到Exporters頁籤,使用java5以上的泛型,看要不要用annotation,要在勾。如果不用annotation,就要用hbm.xmlDomain codepersistent classDAO code為建資料庫的程式碼,有需要就可以勾,再來按下Apply後按Run即完成


 

正當我高興時,天殺的,想不到居然發生一個有衝突的例外訊息





忽然很想殺人啊~~~!找了好久,終於找到解法,就是Console改成3.5的即可,但Hibernate Configurations隨便按一下就跳到Error Log頁籤,說我是3.6版的,這時不用管它,只要按到有table出來就表示ok了,後來的操作都一樣,所以我應該一開始就始用3.5就不會出錯了吧!
hibernate現在已經到5.x了還這樣,真是火大沒處發,只好用饅頭丟狗




以下是產生出來的檔案,有可能須要微調一下,自行修改即可


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

※Configuration還有一些其他的用法


在src下增加一個叫hibernate.properties,將cfg.xml的內容變成key=value形式
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.password=your password
hibernate.connection.url=jdbc:oracle:thin:@localhost:1521:db name
hibernate.connection.username=your username
hibernate.dialect=org.hibernate.dialect.OracleDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.default_schema=XXX

new Configuration()就會把hibernate.properties讀進來,但因為沒有hbm.xml,所以要在.addClass(); 如果要在configure()也可以,cfg.xml會把properties的內容覆蓋,但如果要addClass()只能選擇其一,看是要將cfg.xml的mapping註解或是不addClass(),否則會出現Duplicate collection role mapping 的錯誤
Configuration cfg = new Configuration().addClass(Dept2.class).addClass(Emp2.class);
還有一種是什麼檔都不用,直接寫在程式上,如下:
Configuration cfg = new Configuration()
.addClass(Dept2.class)
.addClass(Emp2.class)
.setProperty("hibernate.connection.driver_class", "oracle.jdbc.driver.OracleDriver")
.setProperty("hibernate.connection.password", "your password")
.setProperty("hibernate.connection.url", "jdbc:oracle:thin:@localhost:1521:db name")
.setProperty("hibernate.connection.username", "your username")
.setProperty("hibernate.dialect", "org.hibernate.dialect.OracleDialect")
.setProperty("hibernate.show_sql", "true")
.setProperty("hibernate.format_sql", "true")
.setProperty("hibernate.default_schema", "XXX");

綜合以上的寫法,最好用的還是cfg.xml配合hbm.xml,所以這種方式最為廣泛
※一對多,多對一
員工對部門是多對一
public class Emp2 {
    private Integer empno;
    private String ename;
    private String job;
    private Date hiredate;
    private Float sal;
    private Float comm;
    // 多對一
    private Dept2 deptno;
    //...
    
    

部門對員工是一對多
public class Dept2 {
    private Integer deptno;
    private String dname;
    private String loc;
    // 一對多
    private Set<Emp2> emps = new HashSet<>();
    
    
    
    //...

最後用hibernate tools使用hbm.xml的工具會直接產生
<many-to-one name="deptno" class="vo.Dept2" fetch="join">
    <column name="DEPTNO" />
</many-to-one>

<set name="emps" table="EMP2" inverse="false" lazy="true">
    <key>
        <column name="DEPTNO" />
    </key>
    <one-to-many class="vo.Emp2" />
</set>

如果改成List會變成以下的樣子,多個<list-index>
<list name="emps" inverse="false" table="EMP2" lazy="true">
    <key>
        <column name="DEPTNO" />
    </key>
    <list-index></list-index>
    <one-to-many class="vo.Emp2" />
</list>

如果沒有主鍵,會自動變成複合主鍵,composite-id裡面合起來就是複合主鍵,最外層又包了一層

@EmbeddedId表示複合主鍵ID
@AttributeOverrides包住@AttributeOverride,裡面放複合屬性

※NUMBER(precision, scale),precision為全部位數,不包括小數點; scale為小數點後長度
number(5, 2)-->123.45,如果最後是0不顯示(這我不確定)
number(3, 0)-->789


@Embeddable表示為複合主鍵類
 

我這一篇又更詳細一點-->複合主鍵 (Hibernate3.x 十五)

沒有留言:

張貼留言