we are currently migrating from MSSQL to Oracle and we dont want to use the hibernate_sequence for all tables. Each table should have its own Sequence.
We already did the change in our testenvironment but I'd like to get some additional info if our solution is safe to use..
Most of our classes are extending from baseentities but we also have a couple of stand-alone entities.
What we changed:
-baseentities(#MappedSuperclass):
changed: #GeneratedValue(strategy = GenerationType.AUTO)
to: #GeneratedValue(strategy = GenerationType.AUTO, generator = "HIBERNATE_GENERATOR")
-extending entities:
added after the #Table annotation:
#SequenceGenerator(name = "HIBERNATE_GENERATOR", sequenceName = "${TABLENAME}_SEQ")
-stand-alone entities:
added after the #Table annotation:
#SequenceGenerator(name = "HIBERNATE_GENERATOR", sequenceName = "${TABLENAME}_SEQ")
changed : #GeneratedValue(strategy = GenerationType.AUTO)
to: #GeneratedValue(strategy = GenerationType.AUTO, generator = "HIBERNATE_GENERATOR")
So we are using always the same generatorname "HIBERNATE_GENERATOR", only the sequenceNames are different.
Our applications seems to work fine, but is it safe to use always the same generatorname?
No, it's not safe. My guess is that all your generated values are generated by the same sequence. Indeed, the javadoc says:
Defines a primary key generator that may be referenced by name when a generator element is specified for the 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).
(emphasis mine)
Each entity should define its own generator.
Related
I have a java spring boot project which needs to be run on both MySQL and Oracle databases. The project has multiple entities with primary keys set to auto-increment in the db.
I have identified that Hibernate's #GenericGenerator in native strategy will support both MySQL (as IDENTITY) and Oracle (as SEQUENCE) in terms of auto-increment depending on the type of db. But I can't seem to find how to set the allocationSize in the GenericGenerator, for an oracle sequence. I want the allocationSize to be set to 1.
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator="gen")
#GenericGenerator(name = "gen", strategy = "native")
#Column(name = "id", nullable = false)
private Long id;
//Getter and Setter
#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.
check this link below: - Hibernate, #SequenceGenerator and allocationSize
I am trying to have separate auto incremented id generator for each of my entities.
The target database is a SQL Server database, and I am using Hibernate 5.2.4.Final. Also I am generating the tables from code.
I have an abstract BaseEntity and other child entities like below, and thus, I am aiming for TABLE_PER_CLASS.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity {
protected long id;
#Id
#GeneratedValue(strategy = GenerationType.XXX)
#Column(name = "Id")
public long getId() {
return id;
}
}
#Entity
#Table(name = "Tags")
public class Tag extends BaseEntity {
}
Below are the different scenarios that I have faced so far:
setting XXX to AUTO: Creates a hibernate_sequence table in database, which I assume, will not provide separate id sequence for separate table.
setting XXX to SEQUENCE: Same as above. Referred this, while doing it.
setting XXX to TABLE: Creates a hibernate_sequences table, which can provide separate id sequence for separate table. However, I have found out that this is quite expensive (same reference as above), and also not my preferred strategy.
setting XXX to TABLE: Does not work for TABLE_PER_CLASS.
What I actually want to use is the native identity column of SQL Server. However, using the SEQUENCE is also an option, but I am not sure how to create and use one for each table from hibernate. Please suggest how either one of these two can be achieved.
Update on the answer by Khalil M. I tried it in 2 possible ways:
applying on BaseEntity -> does not create a separate sequence for each table, and rather creates a ID_SEQNCE, which queried before saving every new entity. So, I am not sure how this is any different than using GenerationType.TABLE.
applying it on each individual entity class -> while saving, the generator creates duplicate id.
for creating a sequence use this
#Id
#GeneratedValue(generator = "ID_SEQ", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "ID_SEQ", sequenceName = "ID_SEQNCE",allocationSize=1)
Edit:
You have to make it by yourself because what you are asking is not supported in Table per class
the id has to be shared across several tables. Consequently, when
using this strategy, you should not use AUTO nor IDENTITY.
for more info
Use strategy = GenerationType.IDENTITY
A short example is below
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
The GenerationType.IDENTITY is the easiest to use but not the best one from a performance point of view. It relies on an auto-incremented database column and lets the database generate a new value with each insert operation. From a database point of view, this is very efficient because the auto-increment columns are highly optimized, and it doesn’t require any additional statements.
I'm trying to use a defined sequence generation in Oracle JPA, along with GenerationType.AUTO like this:
#Id
#SequenceGenerator(name = "MY_GEN_NAME", sequenceName = "MY_SQ_NAME")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "MY_GEN_NAME")
#Column(name = "ID", nullable = false)
private Long id;
After running the hibernate validation it throws an error:
Schema validation: missing sequence [hibernate_sequence]
I guess, it is ignoring my MY_GEN_NAME and trying to use that global sequence for id generation.
When I switch to GenerationType.SEQUENCE, it uses SequenceHiLoGenerator and it works fine.
Why is that happening, and is it possible to make the GenerationType.AUTO work with given sequence for Oracle (possibility to switch to other db)?
AUTO says to the JPA provider, "choose what you want", and it will not use the "generator" attribute in that case.
If you want to use a SEQUENCE then set the strategy to SEQUENCE! That way it will use the sequence definition you have defined
Though hibernate-sequence-on-oracle-generatedvaluestrategy-generationtype-auto suggests that this will work, it appears that it is broken for some versions of Hibernate, see HHH-10656.
Edit: Broken in 5.2.0, unbroken in 5.2.8.
I am using JPA 2.1 with Hibernate 4.3.8. on Oracle, MySQL, PostgreSQL and MS SQL. For creating numeric primary keys I have used the following code :
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "t_gen")
#SequenceGenerator(name = "t_gen", sequenceName = "T_SEQ")
private long id;
So far so good. But I need to generate only positive values of IDs under all conditions. How can I force Hibernate to generate only positive ID's on each database (MS SQL, MySQL, PostgreSQL, Oracle) ?
Hope this helps;
If allocationSize is not declared on the entity side, as default allocation size is 50 ALL sequences MUST declare INCREMENT BY 50 on the DB side.
Reference Link:
http://skay-dev.blogspot.in/2013/09/hibernate-sequence-and-negative.html
There is a JSF/JPA application with EclipseLink2 which has about 40 different Entity classes. The method used to generate the id for every Entity class is AUTO.
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
After about one weeks run in production, the Id numbers has passed more than 10,000. I am worries about the possibility of running out the long numbers in few years time.
So I searched the net and changed the Id Generation Strategy as below.
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "item_entity_seq_gen")
#SequenceGenerator(name = "item_entity_seq_gen", sequenceName = "ITEM_ENTITY_SEQ")
Long id;
But when a new Entity is been created, there is an error as follows.
How can I change the auto generation strategy so that there will be no threat to running out of long ids after the development stage.
Thanks in advance
As isnot2bad stated in the comment, it is practically impossible to run out if auto-generated ids and I have given up the new method of generating seperate Ids.