64

Sometimes I find them together, sometimes alone... other times they seem to do the same.

What's the difference?

Here are three examples. What do they do of different? Why can't I use just @GeneratedValue for all of them?

Example 1

@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment") 
Long id;

Example 2

@Id @GeneratedValue(strategy=GenerationType.SEQUENCE)
private int userId;

Example 3

@ElementCollection
@JoinTable(name="Address",
   joinColumns=@JoinColumn(name="user_id")
)
@GenericGenerator(name="hilo-gen", strategy="hilo")
@CollectionId(columns = @Column(name="Address_id"), generator = "hilo-gen", type = @Type(type="long"))
Collection<Addr> listOfAddresses = new ArrayList<Addr>();
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
user1883212
  • 7,539
  • 11
  • 46
  • 82

3 Answers3

89

When using an ORM it is often necessary to generate a primary key value.

The @GeneratedValue annotation denotes that a value for a column, which must be annotated with @Id is generated. The elements strategy and generator on the annotation describe how the generated value is obtained.

There are four possible values for the strategy element on the @GeneratedValue annotation: IDENTITY, AUTO, TABLE and SEQUENCE. See more.

So to answer Part 2 of your question, the code snippet is indicating that the value of userId will be obtained through a sequence in the database.

The generator element of the @GeneratedValue annotation denotes the name of the primary key generator. In Part1 of your question, the code snippet indicates that a generator named increment will be used to obtain the primary key value. increment is then defined in the next annotation @GenericGenerator. @GenericGenerator is a hibernate annotation used to denote a custom generator, which can be a class or shortcut to a generator supplied by Hibernate. increment is a shortcut to a Hibernate generator that:

generates identifiers of type long, short or int that are unique only when no other process is inserting data into the same table. Do not use in a cluster.

In the Third Part of your question, the code uses a hilo Hibernate generator that:

uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int, given a table and column (by default hibernate_unique_key and next_hi respectively) as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
17

To extend the @kevin-bowersox's answer.
Relationships between the Hibernate primary key generation strategies and specific generator respectively, as specified in org.hibernate.id.IdentifierGeneratorFactory

static {
    GENERATORS.put("uuid", UUIDHexGenerator.class);     // "deprecated" for new use
    GENERATORS.put("hilo", TableHiLoGenerator.class);   // removed in Hibernate 5
    GENERATORS.put("assigned", Assigned.class);
    GENERATORS.put("identity", IdentityGenerator.class);
    GENERATORS.put("select", SelectGenerator.class);
    GENERATORS.put("sequence", SequenceGenerator.class);
    GENERATORS.put("seqhilo", SequenceHiLoGenerator.class);
    GENERATORS.put("increment", IncrementGenerator.class);
    GENERATORS.put("foreign", ForeignGenerator.class);
    GENERATORS.put("guid", GUIDGenerator.class);
    GENERATORS.put("uuid.hex", UUIDHexGenerator.class); // uuid.hex is deprecated
    GENERATORS.put("sequence-identity", SequenceIdentityGenerator.class);
}

In Hibernate 4.3 I've found org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory class with 3 more strategies:

    register("uuid2", UUIDGenerator.class);
    register("enhanced-sequence", SequenceStyleGenerator.class);
    register("enhanced-table", TableGenerator.class);

The above fifteen strategies, plus native, are sixteen generation strategies supported in Hibernate by default.

Example with native:

@GeneratedValue(generator = "nativeGenerator")
@GenericGenerator(name = "nativeGenerator", strategy = "native")
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
11
@Entity
@Table(name="Honey")
public class Honey implements Serializable{
    private static final long serialVersionUID = 42L;
    @Id
    //@SequenceGenerator(name="honeySequence",sequenceName="HONEY_SEQ")
    @org.hibernate.annotations.GenericGenerator(name="honeySequence", strategy = "sequence", 
    parameters = { 
            @Parameter(name="sequence", value="HONEY_SEQ") } 
    )
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="honeySequence")
    private int Id;
    private String name;
    private String taste;
  • @GeneratedValue is used only to get the generated value. The two arguments strategy and generator are used to define how the value is obtained.
  • @GenericGenerator is used to map a user defined sequence generator with your hibernate session.
  • You can also use @SequenceGenerator which i have commented in my code. This is not a simple sequence generator but a generator which work on HILO algorithm. Due to which you will find a lot of gaps in your sequence, like your first value will start from 50 because the default allocation size is 50.

So its better to use @GenericGenerator for your own architecture. But if you are bound to use @SequenceGenerator you have to manually edit your sequence to have two more attributes allocationSize=1 and initialValue=1. And to work with these attributes you need to add apropert in your hibernate.cfg.xml file

<property name="hibernate.id.new_generator_mappings">true</property>
Mohd Faizan Khan
  • 437
  • 1
  • 5
  • 16
  • I know this is an old post. So in your example above, is the sequence "HONEY_SEQ" a sequence created for that table in the actual database (Oracle, DB2 etc...)? – user320550 Mar 26 '18 at 08:15
  • Yes. HONEY_SEQ is a the name of the database sequence as it is created on the database. – cogitoboy Mar 01 '19 at 18:09
  • Hi @cogitoboy, will the "HONEY_SEQ" be created automatically by Hibernate or i need to create it on the database? – jumping_monkey Oct 22 '19 at 07:34
  • 1
    @jumping_monkey, hibernate can't create a seq, you need to create a db seq manually. – Mohd Faizan Khan Oct 23 '19 at 01:52
  • Thanks @MohdFaizanKhan, that was what i was thinking. It never worked until i created it manually. That would be a "nice-to-have" feature though. – jumping_monkey Oct 23 '19 at 07:22