Oracle实现主键自增长的几种方式

时间:2024-02-24 17:21:28

使用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。