※Hibernate3.x的Hello World
用maven創一個空專案後,去http://mvnrepository.com,將hibernate和javassist的dependency貼到pom.xml裡,如果不下載javassist執行會有錯誤提示,還有資料庫的驅動程式也要加。
設定好後,寫一個對應DB的java 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 版
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的類
@ID為DB主鍵
@Column為DB的欄位
要完全和DB的欄位一模一樣才可以
annotation也可以寫在setter/getter上面
annotation也可以寫在setter/getter上面
但DB常常有底線,所以java連不到,所以還可以這樣寫
@GeneratedValue是設定流水號之類用的
這樣子java的屬性就可以亂打了,但唯一就是@Id,沒有name可以設定,我目前也沒找到其他方法,所以目前就Id先和DB的欄位名稱一樣,其他隨便,測試類和XML設定一樣
值得一提的就是,如果使用hbm.xml,而且annotation也寫了,而且還亂寫,還是能執行成功,感覺應該是annotation沒作用而已
※用功具生成class
在src下增加一個叫hibernate.properties,將cfg.xml的內容變成key=value形式
new Configuration()就會把hibernate.properties讀進來,但因為沒有hbm.xml,所以要在.addClass(); 如果要在configure()也可以,cfg.xml會把properties的內容覆蓋,但如果要addClass()只能選擇其一,看是要將cfg.xml的mapping註解或是不addClass(),否則會出現Duplicate collection role mapping 的錯誤
綜合以上的寫法,最好用的還是cfg.xml配合hbm.xml,所以這種方式最為廣泛
※一對多,多對一
員工對部門是多對一
部門對員工是一對多
最後用hibernate tools使用hbm.xml的工具會直接產生
如果改成List會變成以下的樣子,多個<list-index>
值得一提的就是,如果使用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名都為資料庫用戶名的原因。
※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,給個名字,通常是專案名稱加_configuration,reveng.xml選已存在的
選剛剛建立的reveng.xml
切換到Exporters頁籤,使用java5以上的泛型,看要不要用annotation,要在勾。如果不用annotation,就要用hbm.xml,Domain code為persistent
class,DAO code為建資料庫的程式碼,有需要就可以勾,再來按下Apply後按Run即完成
正當我高興時,天殺的,想不到居然發生一個有衝突的例外訊息
忽然很想殺人啊~~~!找了好久,終於找到解法,就是Console改成3.5的即可,但Hibernate
Configurations隨便按一下就跳到Error Log頁籤,說我是3.6版的,這時不用管它,只要按到有table出來就表示ok了,後來的操作都一樣,所以我應該一開始就始用3.5就不會出錯了吧!
hibernate現在已經到5.x了還這樣,真是火大沒處發,只好用饅頭丟狗
hibernate現在已經到5.x了還這樣,真是火大沒處發,只好用饅頭丟狗
以下是產生出來的檔案,有可能須要微調一下,自行修改即可
------------------------------------------------------------------------------------------------------------
※Configuration還有一些其他的用法
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表示為複合主鍵類
number(5, 2)-->123.45,如果最後是0不顯示(這我不確定)
number(3, 0)-->789
@Embeddable表示為複合主鍵類
我這一篇又更詳細一點-->複合主鍵 (Hibernate3.x 十五)
沒有留言:
張貼留言