标签:
每张表都有主键,可分别简单主键和组合主键,简单主键为表中的一列,组合主键为表中的几列。主键的生成策略有许多种,其中,序列是oracle常见的主键生成策略之一。本文主要讲解JPA映射主键的技术细节。其中,主键生成策略是oracle序列,JPA实现是Hibernate。
drop sequence testsequence; Create sequence testsequence Increment by 1 Start with 1 NOMAXVALUE NOMINVALUE Nocycle nocache;
序列testsequence,从1开始递增,每次递增1。不指定最大值、最小值、不循环、不缓存。
create table TEST ( id NUMBER not null, name VARCHAR2(30) ) ; alter table TEST add constraint PK_ID primary key (ID); create table TEST2 ( id NUMBER not null, name VARCHAR2(30) ) ; alter table TEST2 add constraint PK_TEST2_ID primary key (ID);
创建了两张表,TEST、TEST2。表结构完全一致,简单主键ID,名字name。
CREATE OR REPLACE TRIGGER "TG_TEST" BEFORE INSERT ON TEST FOR EACH ROW WHEN (new.id is null) begin select testsequence.nextval into:new.id from dual; end; / ALTER TRIGGER "TG_TEST" ENABLE; CREATE OR REPLACE TRIGGER "TG_TEST2" BEFORE INSERT ON TEST2 FOR EACH ROW WHEN (new.id is null) begin select testsequence.nextval into:new.id from dual; end; / ALTER TRIGGER "TG_TEST" ENABLE;
定义两张表TEST、TEST2的主键生成策略是序列testsequence。
private long id;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
@SequenceGenerator(name="sequence", sequenceName="testSequence", initialValue=1, allocationSize=1)
@Column(name = "ID")
public long getId()
{
return this.id;
}
public void setId(long id)
{
this.id = id;
}@SequenceGenerator,属性name,表示序列定义的名称,属性sequenceName,表示序列的名称。这两个属性的解释很像,但并非一回事。属性name指的是序列定义本身的名称,属性sequenceName表示该定义涉及到的序列的名称。属性initialValue,表示序列初始值,属性allocationSize,表示序列递增或递减的幅度。 Test test = new Test();
test.setName("John Wiley & Sons");
manager.persist(test);查询数据库,数据的情况如下: /**
* (Optional) The value from which the sequence object
* is to start generating.
*/
int initialValue() default 1;
/**
* (Optional) The amount to increment by when allocating
* sequence numbers from the sequence.
*/
int allocationSize() default 50;但是,根据测试,结果并非如源代码展示的那样。以上序列重新建立、清空表TEST的数据,把@SequenceGenerator的属性initialValue、 allocationSize去掉,保持默认。执行持久化实体的动作。/**
* Defines a primary key generator that may be referenced by name when
* a generator element is specified for the {@link GeneratedValue}
* annotation. A sequence generator may be specified on the entity
* class or on the primary key field or property. The scope of the
* generator name is global to the persistence unit (across all
* generator types).
*
* <pre>
* Example:
*
* @SequenceGenerator(name="EMP_SEQ", allocationSize=25)
* </pre>
*
* @since Java Persistence 1.0
*/但是,根据测试,在持久化单元内,序列定义只针对定义它的实体有效。在实体TEST内定义了一个序列定义,名称为sequence。现在在实体TEST2应用这个序列定义。 private long id;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
@Column(name = "ID")
public long getId()
{
return this.id;
}
public void setId(long id)
{
this.id = id;
}private long id;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
@SequenceGenerator(name="sequence", sequenceName="testSequence", initialValue=1, allocationSize=1)
@Column(name = "ID")
public long getId()
{
return this.id;
}
public void setId(long id)
{
this.id = id;
}以上代码,在实体TEST2内,针对序列testSequence,重新定义了序列定义,持久化一切正常。因此,序列定义只针对定义它的实体有效。在生产环境中,不同的表应该使用不同的序列。这样才能最大限度保证序列产生的数值在特定的表中,其主键数值具有连续性。比如说,一个序列产生的数值类似1、2、3、4、5......在该序列同时应用在表TEST,TEST2,有可能数值1、2分配给了TEST,而把3、4、5分配给了TEST2,这样看起来,表中的主键数值就常常没有连续性。当然,序列只分配给某个表,也不能保证该表的主键数值就一定会有连续性。当遇到事务回滚时,序列产生的数值同样没有插入到表的主键,造成主键数值的不连续。标签:
原文地址:http://blog.csdn.net/seedshome/article/details/52170893