使用SQLServer、MySQL時,無論我們使用的是直接JDBC連接數據庫,還是通過Hibernate操縱數據庫,我們只需要設置一個選項或者一行注解便可以實現主鍵的自增長。
但Oracle沒有直接提供主鍵自增長的功能,這里我們可以使用兩種方式來解決主鍵自增長的問題。
第一種,通過序列以及觸發器實現主鍵自增長。
這種方式適用於直接使用JDBC連接數據庫。這種方式將主鍵自增長的任務完全交給數據庫,我們無需在代碼層面上進行任何控制。
第二種,通過序列以及Hibernate配置實現自增長。
這種方式適用於通過Hibernate連接數據庫的方式。這種方式在數據庫上創建序列,通過配置在POJO類上的注釋,讓Hibernate去調用數據庫的序列實現自增長。
這兩種方式都是通過Oracle的序列實現自增長,但第一種通過數據庫的觸發器在插入的時候自動插入主鍵。而后者則由Hibernate自動完成獲取主鍵,插入主鍵這一操作。
在用到Hibernate進行開發的項目中,建議選擇第二種進行配置。因為如果通過第一種方式進行配置,則Hibernate無法獲取到其主鍵的值,在插入的時候Hibernate會提示:父類主鍵未找到(即主鍵無值)。
進一步,Hibernate的級聯增加也會因為無法獲取到主鍵而無法插入數據到關系表中。
一、通過序列以及觸發器實現主鍵自增長
首先,為每個表創建一個序列:
1 /* 創建序列 */ 2 --為bitinfo表的主鍵創建序列 3 create sequence bitinfo_id_seq 4 increment by 1 5 start with 1; 6 --為product表的主鍵創建序列 7 create sequence product_id_seq 8 increment by 1 9 start with 1;
接着,為相對於的表創建觸發器:
1 /* 創建觸發器(兩個觸發器請分開執行) */ 2 --為bitinfo表創建觸發器 3 create or replace trigger trg_bitinfo 4 before insert on t_yw_bitinfo 5 for each row 6 begin 7 select bitinfo_id_seq.nextval into :new.id from dual; 8 end trg_bitinfo; 9 --為product表創建觸發器 10 create or replace trigger trg_product 11 before insert on t_yw_product 12 for each row 13 begin 14 select product_id_seq.nextval into :new.id from dual; 15 end trg_product;
你可以使用下面的語句查看序列是否已經創建:
1 --查看某位用戶的所有序列 2 select SEQUENCE_OWNER,SEQUENCE_NAME from dba_sequences where sequence_owner='CSY'; 3 --刪除序列 4 drop sequence bitinfo_id_seq;
二、通過序列以及Hibernate配置實現自增長
首先,為每個表創建一個序列:
1 /* 創建序列 */ 2 --為bitinfo表的主鍵創建序列 3 create sequence bitinfo_id_seq 4 increment by 1 5 start with 1; 6 --為product表的主鍵創建序列 7 create sequence product_id_seq 8 increment by 1 9 start with 1;
接着,把POJO類主鍵上的注釋改為:
1 @Id 2 @SequenceGenerator(name = "prodG",sequenceName="PRODUCT_ID_SEQ",allocationSize=1) 3 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "prodG") 4 public int getId() { 5 return id; 6 }
其中第2、3行聲明該主鍵使用序列來實現自增長,第2行的sequenceName指定了序列名(即在上一步驟所創建的序列名)。
第2行的allocationSize指定了自增長的大小,這里手動設置為1。在Hibernate Annotation版本(大概是3.2版本)之前,如果不設置這個屬性,其默認為1。
但在3.2版本之后如果不設置allocationSize,則其自增長大小變成50。