By default, Hibernate uses a single global sequence called hibernate_sequence. So if a customer record adds, and id generates 100 while next I add a country record and id generates 101.
in Country Model
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="CTRY_ID")
private long ctryID;
in Customer Model
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="CUST_ID")
private long custID;
I want separate mechanism for both customer and country tables i.e.
Last Id stored in Customer table is 91, so on next record being add, id become 92. And similar way, Last Id stored in Country is 82, so next record, Id should be 83.
How could I achieve this behavior in Spring Boot/Oracle.
You should try creating a custom sequence using #SequenceGenerator annotation. You can set initial value of sequence initialValue = 1 and allocationSize=1is for increment. If you won't use allocationSize=1 hibernate uses the default allocation size which is 50.
For Country:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="ctry_seq")
#SequenceGenerator(name = "ctry_seq", sequenceName = "ctry_seq", initialValue = 1, allocationSize=1)
#Column(name="CTRY_ID")
private long ctryID;
For Customer:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="cust_seq")
#SequenceGenerator(name = "cust_seq", sequenceName = "cust_seq", initialValue = 1, allocationSize=1)
#Column(name="CUST_ID")
private long custID;
You need to define a sequence in your database, use #SequenceGenerator and mark your field as generated by db (#GeneratedValue):
CREATE SEQUENCE seq
MINVALUE 1
MAXVALUE 1000000
START WITH 1
INCREMENT BY 1
CACHE 100;
Entities:
#SequenceGenerator(name="seq", initialValue=1, allocationSize=100)
public class Country {
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
#Id long id;
}
Same with the other one - separate sequence generator.
Related
#Table(name = "CACHING_DATA")
#Entity
public class CachingData implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CACHING_SEQUENCE")
private Long id;
private String protocolecode;
private String uuid;
}
I have above entity class and oracle sequence. But I am getting following error.
Caused by: org.hibernate.MappingException: The increment size of the [CACHING_SEQUENCE] sequence is set to [50] in the entity mapping while the associated database sequence increment size is 1.
You can use allocationSize = 1 for the sequence
#SequenceGenerator(name = "SomeNameForTheGenerator", sequenceName = "CACHING_SEQUENCE", allocationSize = 1)
here the samish issue: org.hibernate.MappingException: The increment size of the sequence is set to [10] in the entity mapping while ... size is [1]
I have a working code, but I don't understand why it works:
public class FeatureInstalled implements Serializable
{
#Id
#Column(name = "FEATURE_INSTALLED_ID")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "FEATURE_INSTALLED_Sequence")
#SequenceGenerator(name = "FEATURE_INSTALLED_Sequence", sequenceName = "FEATURE_INSTALLED_SEQ", allocationSize = 1)
private Long featureInstalledId;
This gets the FEATURE_INSTALLED_ID from the sequence and uses it to insert a record.
I had the following code without allocationSize and although it appeared to use generated IDs, it had much larger FEATURE_INSTALLED_IDs:
public class FeatureInstalled implements Serializable
{
#Id
#Column(name = "FEATURE_INSTALLED_ID")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "id_Sequence")
#SequenceGenerator(name = "id_Sequence", sequenceName = "FEATURE_INSTALLED_SEQ")
private Long featureInstalledId;
Can someone explain to me why it works so strange without allocationSize and confirm that it works with it? Btw. There is also a trigger defined on the FEATURE_INSTALLED-table for FEATURE_INSTALLED_ID being NULL.
The allocationSize attribute in the #SequenceGenerator annotation is optional, so if allocationSize is absent the #SequenceGenerator works fine with a default value at 50. Thus, the sequence generator increments the values by 50.
As mentioned in the documentation, here, of the #SequenceGenerator:
allocationSize
public abstract int allocationSize (Optional) The amount to increment
by when allocating sequence numbers from the sequence. Default: 50
There is already some data available in table, where id being the primary key for me. So when i trying to invoke my spring jpa code to add values to the table i'm using #GeneratedValue for the primary key.
But this way is generating value which is already present in DB. so my application is throwing an exception.
Is there any way i can get the current value from the table and increment my primary key id wrt the previous value of ID present in the table
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "id", updatable = false, nullable = false)
private int id;
Let's say your max id in DB currently is 500. Run this:
CREATE SEQUENCE seq_name_in_db START WITH 501;
And change to:
#Id
#SequenceGenerator(name = "some_seq", sequenceName = "seq_name_in_db")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "some_seq")
private int id;
UPDATE: (Solution to OP's comment)
While inserting directly, do this:
INSERT INTO some_table (id, ...) VALUES (seq_name_in_db.NEXTVAL, ...);
When You create the sequence, you can let it start with a certain value e.g.
CREATE SEQUENCE XX_SEQ
START WITH 100
INCREMENT BY 1 ;
I wanted to generate sequence using hibernate tool ( pojo to sql). And definitely it works fine.
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqid-gen")
#SequenceGenerator(name = "seqid-gen", sequenceName = "RTDS_ADSINPUT_SEQ" )
#Column(name="id")
public Long getId() {
return id;
}
This code generates below sql
create sequence RTDS_ADSINPUT_SEQ;
The problem is I wanted to specify properties like
START WITH, INCREMENT BY, NOCACHE
and the final ddl script should be some thing like below
CREATE SEQUENCE RTDS_ADSINPUT_SEQ MINVALUE 1 MAXVALUE
999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE;
But as far I saw hibernate only support name, sequncename, allocationSize, initialvalue. My doubt is, if we use allocationSize = 1 & initialValue = 1 do we still need to mention "nocache". If so, do we have any kind of annotation for "nocache"?
Please advice me if I can include that properties as annotation in the pojo.
sequence use only oracle, postgreSQL, DB2, H2
I know two case.
(1)
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int idx;
Auto_increment, sequence object -> strategy = GenerationType.AUTO
(2)
Your case.
Element Detail
public abstract String name (Required) A unique generator name that
can be referenced by one or more classes to be the generator for
primary key values.
public abstract String sequenceName (Optional) The name of the
database sequence object from which to obtain primary key values.
Defaults to a provider-chosen value. Default: hibernate_sequence
public abstract int initialValue (Optional) The value from which the
sequence object is to start generating. Default:1
public abstract int allocationSize (Optional) The amount to increment
by when allocating sequence numbers from the sequence. Default:50
DDL
create sequence RTDS_ADSINPUT_SEQ start with 1 increment by 1;
Entity
#Entity
#SequenceGenerator(
name = "seqid-gen",
sequenceName = "RTDS_ADSINPUT_SEQ"
initiaValue = 1, allocationSize = 1)
public class XXX {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqid-gen")
private long id;
//getter, setter
}
As i know we do not have such annotation properties. But ideally, you should create the sequence using your own SQL query instead using the default one generated by hibernate. When the sequence existed in database, Hibernate will not generate one, you can also disable hibernate ddl generation.
We can generate sequence id using hibernate in below mentioned manner
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int uniqueid;
I have an entity simply called Order. The strategy I'm using now for the ID is:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ORDER_ID")
private Long id;
Now, hardcoding another startvalue seems easy:
#Entity
#SequenceGenerator(name = "SequenceIdGenerator",
sequenceName = "SEQ_ID_GEN", initialValue = 50,
allocationSize = 20)
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SequenceIdGenerator")
#Column(name = "ORDER_ID")
private Long id;
But that's hardcoded to 50. Can I set that value dynamically? Best would be if I could have it stored in the database or in a properties file?
Or is it not best practice to set id dynamically?
Usually, but not always, the easiest way is to create a sequence in your database and to use that sequence. I hope there is not much mistakes in following example:
#Id
#GeneratedValue(generator="IdSeq")
#SequenceGenerator(name="IdSeq",sequenceName="SEQ_ID_GEN", allocationSize=20)