views:

660

answers:

4

I have some code:

@Id
@SequenceGenerator(name = "SOMETHING_SEQ")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SOMETHING_SEQ")
@Column(name = "SOMETHING", nullable = false)
private Long id;

How is hibernate providing my id?

I see in my database there a single sequence named 'hibernate_sequence' and no other hibernate 'special tables'.

A: 

In Oracle you don't have the auto_increment type as in MySQL. So, to generate an auto_increment column you need to use a sequence.

This is an example of how you can achieve this.

create table test (id number, testdata varchar2(255)); 


create sequence test_seq 
start with 1 
increment by 1 
nomaxvalue; 

create trigger test_trigger
before insert on test
for each row
begin
select test_seq.nextval into :new.id from dual;
end;

So you create a sequence and use a trigger before each row is inserted to add its id.

So hibernate must be doing something like this, or instead of using the trigger doing

insert into test values(test_seq.nextval, 'no trigger needed!');

Note: Example taken from here

Lombo
Thank-you. Indeed Oracle does not have the auto_increment capability. However, when i save my @Entity's i leave my @Id fields null. Which then the EntityManager somehow generates an id from somewhere and inserts it. I know this when i enable the SQL output to the console. So coming back to my question, from where does this id come from with my configuration?
JavaRocky
it uses the sequence for sure. Now if it uses the trigger, or the inline insert, configure hibernate to show sql or check if a trigger was generated
Lombo
Hibernate doesn't use a trigger, it just gets the `nextval` on insert.
Pascal Thivent
+2  A: 

Actually, here your SOMETHING_SEQ is the name of sequence you configured somewhere in your hibernate config. And hibernate_sequence is the sequence name in the database. In configuration it would be looking something like below,

<sequence-generator name="SOMETHING_SEQ" 
    sequence-name="hibernate_sequence"
    allocation-size="<any_number_value>"/>

You can completely skip this configuration by using annotation instead. Then your @SequenceGenerator annotation would need to provide few more paramters. Below is the example.

@SequenceGenerator(name="SOMETHING_SEQ", sequenceName="hibernate_sequence", allocationSize=10)

For example multiple entity classes would do something like below,

@Entity
public class Entity1 {
  @Id
  @SequenceGenerator(name = "entity1Seq", sequenceName="ENTITY1_SEQ", allocationSize=1)
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "entity1Seq")
  @Column(name = "ID", nullable = false)
  private Long id;

  ...
  ...

}

@Entity
public class Entity2 {
  @Id
  @SequenceGenerator(name = "entity2Seq", sequenceName="ENTITY2_SEQ", allocationSize=10)
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "entity2Seq")
  @Column(name = "ID", nullable = false)
  private Long id;

  ...
  ...

}
Adeel Ansari
Thanks. But in my case, how is hibernate providing my id? As when i save my entity with a null value for my Long id, it magically is auto inserted. Is it via some special table, or using that hibernate_sequence? Or..?
JavaRocky
Using the `hibernate-seq`, and of course when you said Hibernate to generate it, you must not provide any yourself. Or even if you provide some value per say, that value would get overwritten.
Adeel Ansari
Are you saying multiple entities share this same hibernate sequence?
JavaRocky
Not necessarily. You can define otherwise, check my addemdum. If you defined just one sequence for every entity, then yes it will use the same sequence.
Adeel Ansari
+1  A: 

In order to name the sequence you have to set the sequenceName in your @SequenceGenerator annotation.

@GeneratedValue(name="gen", strategy = GeneratorType.SEQUENCE) @SequenceGenerator(name="gen", sequenceNAme="Sequence_Name", allocationSize = 1) @Id public Long getId() { ... }

Of note, if you are using a pre-existing generator, your allocationSize must match the allocation size of that generator.

kgrad
+1  A: 

How is hibernate providing my id?

Well, you explicitly told the JPA engine to generate identifier automatically (with the @GeneratedValue annotation) using a strategy of type SEQUENCE indicating that a database sequence should be used to generate the identifier. In case you wonder, sequences are database specific objects (e.g. Oracle) that can be used to generate unique integers.

I see in my database there a single sequence named 'hibernate_sequence'

You didn't use the sequenceName annotation element in your @SequenceGenerator to specify the name of the database sequence object to use so Hibernate created a default sequence object during schema generation (which defaults to hibernate_sequence). To specify a sequence, do it like this:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_entity_seq_gen")
@SequenceGenerator(name = "my_entity_seq_gen", sequenceName="MY_ENTITY_SEQ")
private Long id;
Pascal Thivent
Equally good answer
JavaRocky