在Hibernate中實現Oracle的自動增長
根據hibernate的文檔,有兩種方式實現實體對象的主鍵自動增長。
***種:設置ID的增長策略是sequence,同時指定sequence的名字,***每個表建一個sequence,此種做法就如同MS-SQL,MY-SQL中的自動增長一樣,不需要創建觸發器,具體的oracle數據庫腳本及hibernate配置文件如下:
[1]oracle數據表的創建腳本:
- CREATE TABLE DEPARTMENT (
- ID NUMBER(19,0) DEFAULT '0' NOT NULL,
- NAME VARCHAR2(255) NOT NULL,
- DESCRIPTION CLOB
- );
- ALTER TABLE DEPARTMENT ADD CONSTRAINT PRIMARY_0 PRIMARY KEY(ID) ENABLE;
- ALTER TABLE DEPARTMENT ADD CONSTRAINT UK_DEPARTMENT_1 UNIQUE (NAME);
- CREATE SEQUENCE DEPARTMENT_ID_SEQ MINVALUE 10000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;
創建DEPARTMENT表,并為DEPARTMENT表創建一個單獨的SEQUENCE,名字為SEQUENCE_ID_SEQ,并不需要創建觸發器。
[2]hibernate映射文件的配置:
- < ?xml version="1.0"?>
- < !DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- < hibernate-mapping package="com.liyanframework.demo.domain">
- < class name="Department" table="DEPARTMENT">
- < id name="id" column="ID">
- < generator class="sequence">
- < param name="sequence">DEPARTMENT_ID_SEQ< /param>
- < /generator>
- < /id>
- < property name="name" column="NAME" type="string" />
- < property name="description" column="DESCRIPTION" type="text" />
- < /class>
- < /hibernate-mapping>
在hibernate映射文件中,對ID的生成策略選擇sequence,指定sequence的名字DEPARTMENT_ID_SEQ就可以了,當你保存新對象的時候,hibernate會自動取得DEPARTMENT_ID_SEQ.NEXTVAL作為新對象的ID保存到數據庫,所以不需要再使用觸發器再來生成新記錄的ID。
第二種:設置ID的增長策略是native,但是需要創建一個名字為hibernate_sequence(這個名字好像是hibernate默認的 sequence名字,不創建會出錯的)的全局使用的sequence,然后再對每一個表的ID生成的時候,使用觸發器,取得 hibernate_sequence.CURRVAL作為新記錄的ID,具體的oracle數據庫腳本及hibernate配置文件如下:
[1]oracle數據表的創建腳本:
- CREATE TABLE STAFF (
- ID NUMBER(19,0) DEFAULT '0' NOT NULL,
- NAME VARCHAR2(255) NOT NULL,
- AGE NUMBER(3,0) NOT NULL,
- BIRTHDAY DATE NOT NULL,
- SALARY NUMBER(10,2) NOT NULL,
- LEVELNESS FLOAT NOT NULL,
- CREATETIME TIMESTAMP NOT NULL,
- ENABLE CHAR(2) DEFAULT 'Y' NOT NULL,
- STATUS VARCHAR2(64) NOT NULL,
- DEPARTMENT_ID NUMBER(19,0)
- );
- ALTER TABLE STAFF ADD CONSTRAINT PRIMARY_1 PRIMARY KEY(ID) ENABLE;
- ALTER TABLE STAFF ADD CONSTRAINT STAFF_IBFK_0 FOREIGN KEY(DEPARTMENT_ID) REFERENCES DEPARTMENT(ID) ENABLE;
- ALTER TABLE STAFF ADD CONSTRAINT UK_STAFF_1 UNIQUE (NAME);
- CREATE INDEX IDX_STAFF_STATUS ON STAFF(STATUS);
- CREATE SEQUENCE HIBERNATE_SEQUENCE MINVALUE 90000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;
- CREATE OR REPLACE TRIGGER STAFF_ID_TRG BEFORE INSERT ON STAFF
- FOR EACH ROW
- BEGIN
- IF INSERTING AND :NEW.ID IS NULL THEN
- SELECT HIBERNATE_SEQUENCE.CURRVAL INTO :NEW.ID FROM DUAL;
- END IF;
- END;
創建STAFF表,但是并沒有為STAFF創建相應的主鍵sequence,而是創建了一個名字為HIBERNATE_SEQUENCE的 sequence,然后創建一個觸發器STAFF_ID_TRG,當執行INSERT操作時,hibernate會先執行一次 HIBERNATE_SEQUENCE.NEXTVAL,所以在觸發器中只需要取得HIBERNATE_SEQUENCE.CURRVAL作為新記錄的 ID。
[2]hibernate映射文件的配置:
- < ?xml version="1.0"?>
- < !DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- < hibernate-mapping package="com.liyanframework.demo.domain">
- < class name="Staff" table="STAFF">
- < id name="id" column="ID">
- < generator class="native" />
- < /id>
- < property name="name" column="NAME" type="string" />
- < property name="age" column="AGE" type="integer" />
- < property name="birthday" column="BIRTHDAY" type="date" />
- < property name="salary" column="SALARY" type="big_decimal" />
- < property name="level" column="LEVELNESS" type="float" />
- < property name="createTime" column="CREATETIME" type="timestamp" />
- < property name="enable" column="ENABLE" type="character" />
- < property name="status" column="STATUS" type="string" />
- < many-to-one name="department" column="DEPARTMENT_ID" class="Department" />
- < /class>
- < /hibernate-mapping>
在hibernate映射文件中,對ID的生成策略選擇native,hibernate會根據你數據庫的觸發器來生成新記錄的ID。
比較兩種做法,第二種做法也就是hibernate在代碼中,實現了oracle中的觸發器功能。對于不同的情況,選擇不懂的做法。如果新的系統,新建的 oracle數據庫,推薦使用***種做法,簡單,容易移植到其他支持自動增長的數據庫;如果是老的系統,需要把其他數據庫轉換為oracle的,那就要用第二種了,使用native的方式,可以不改動配置文件,兼容oracle和mysql之類帶有自動增長的數據庫。
安裝有oracle數據庫,創建數據庫,總是要創建一個主鍵ID,唯一標示各條記錄,但oracle不支持自動編號,所以還得創建一個SEQUENCE(序列)語句如
create sequence bign nocycle maxvalue 9999999999 start with1;//增加數據
insertintotable (ID,..) values(bign.nextval,..)
在hibernate中的映射文件可這么寫
- < id name="id" type="java.lang.Long" column="ID">
- < generator class="sequence">
- < param name="sequence">bign< /param>
- < /generator>
- < /id>
或
- < id name="id" type="java.lang.Long" column="ID">
- < generator class="increment">
- < /id>
(increment 用與為long,short或者int類型生成唯一標示。只有在沒有其他進程忘同一張表中插入數據時才能使用。在集群下不要使用)