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