Creating sequence in Oracle Programmatically using JPA - java

I am using spring-boot-starter-data-jpa in my Spring boot project to handle DB stuff.
I want to create a sequence in Oracle programmatically.
I have seen many solution which create sequence using raw query but i want to create a sequence from the code. Is there anything i can do using JPA.
I also want to get this sequence number and return it to the caller.
Thanks in advance!!!

First of all, you have to allow Hibernate (one of the JPA implementations available in spring-boot-starter-data-jpa) create DDL statements, so in application.properties:
spring.jpa.hibernate.ddl-auto=create
Note that it is not recommended for production.
Next, annotate your entity in following way:
#Entity
public class SomeEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "my_generator")
#SequenceGenerator(name = "my_generator", sequenceName = "MY_SEQUENCE", allocationSize = 1)
private Long id;
//...
}
Once your application will start, hibernate based on your ddl-auto configuration will create the sequence for you:
Hibernate: create sequence MY_SEQUENCE start with 1 increment by 1
You can read more about ddl-autoconfigurations here.

Related

Hibernate sequence not generated

Im working on a Spring (not Boot!) project, with Hibernate and PostgreSQL database. I also use Flyway for migration.
I use Flyway to generate the schema of the database, and insert initial data to it with given SQL scripts in my resources folder. For this reason, I excluded the hibernate.hbm2ddl.auto property from my hibernate.properties file.
On the startup, the schema is created and the data is inserted to the database, but my problem is, that this way Hibernate doesn't generate its sequence, and I cant save data from the application:
org.postgresql.util.PSQLException: ERROR: relation "hibernate_sequence" does not exist
What can I do with this?
As you didn't provide any code not sure what is wrong there, assume missing #SequenceGenerator annotation, I'll provide the one is working for me.
#Entity
#Table(name = "your_table")
#SequenceGenerator(name = "your_table_id_seq", sequenceName = "your_table_id_seq", allocationSize = 1)
public class YourTable implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "your_table_id_seq")
private Long id;
.
.
.
You need to create a sequence like this:
CREATE SEQUENCE hibernate_sequence START 1;

Which GenerationType is best among AUTO,IDENTITY & TABLE(or Any other best approch) using Hibernate persistence provider?

In my project we are using Oracle and we want to give support for MYSQL also. Oracle have sequence support but MYSQL don't have. which GenerationType is good if we want to support ORACLE and MYSQL with same code base using Hibernate persistence provider among AUTO,IDENTITY & TABLE(or Any other way)?, can any one give brief description about these please?
Ex:
Class POJO{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
------
#GeneratedValue(strategy = GenerationType.IDENTITY)
-----
#GeneratedValue(strategy = GenerationType.TABLE)
------
(or Any other best approch?)
}
You can use
#GeneratedValue(generator = GenerationType.TABLE)
It will work for both Oracle and mySql
Since MySQL supports auto_increment use GenerationType.AUTO for its corresponding POJOs.
For the POJOs for Oracle database you could create a sequence for each and use it in your POJOs as illustrated below.
Sequence creation
CREATE SEQUENCE MY_SEQ
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE
NOCACHE;
Generation type
I suppose the primary key is labeled ID in your Oracle table.
#Id
#GeneratedValue(generator = "mySeq")
#SequenceGenerator(name = "mySeq", sequenceName = "MY_SEQ", allocationSize = 1)
#Basic(optional = false)
#NotNull
#Column(name = "ID")
private Long id;
You may want to look into configuring all the database-dependant stuff in an xml configuration file. I haven't used xml files to configure hibernate for years and I've never mixed it with annotations. But the way I understand it: Your xml configuration will overwrite this specific configuration from your annotations in your POJO.
So you could leave your POJO with your oracle-specific ID Generator, and in case you deploy it for a MySQL, you would need to add an xml configuration with your MySQL-specific ID Generators.
I can't give you any details on this though. sorry.

Hibernate and Oracle: Primary Key constraint violation

In my web application I have multiple scheduled services which work on same entities ( like article, customer...etc). If I run a single service at time I've no problem, but when I run two services I get an error because the primary key unique constraint is violated.
As primary key I use a generated Long value:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
public Long getId() {
return id;
}
Every service read data from a txt file, create its entities and every 20 entities execute a flush on hibernate session followed by a clear. Only at the end of the execution of the service the session is committed.
How can I solve?
Oracle supports only sequences for generated keys. Add a sequence to your database:
CREATE SEQUENCE ARTICLE_SEQ;
Change your annotations to:
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="articleSequence")
#SequenceGenerator(name="articleSequence", sequenceName="ARTICLE_SEQ",allocationSize=1) 
It's best to use a separate sequence for each table/type.
Create sequence in DB and use it like #GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_NAME").

GeneratedValue in Postgres

I have my entity class mapped like below:
#Entity
#Audited
#Table(name="messages_locale")
public class Locale {
#Id
#GeneratedValue
#Getter #Setter //Project Lombok's annotations, equal to generated getter and setter method
private int id;
(...)
I create clean new database ,and properties:
< prop key="hibernate.hbm2ddl.auto" >create < /prop>
WHY THE HELL (Sorry, almost two days wasted on this bug) after created database, i got a sequence in my postgres db?:
CREATE SEQUENCE hibernate_sequence
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 2
CACHE 1;
ALTER TABLE hibernate_sequence
OWNER TO postgres;
I dont want to have a sequence, I want to have just auto increment auto generated values..
I think the accepted answer from Petar is not correct, or not correct any longer. The auto-increment in Postgres is handled through SERIAL pseudo type, that’s correct. However, the mapping that Petar gives will result in the following DDL generated by Hibernate 5.1:
CREATE SEQUENCE users_id_seq START 1 INCREMENT 50;
CREATE TABLE … (
id INT8 NOT NULL,
…
);
This is not using SERIAL, but a Hibernate managed sequence. It is not owned by the table and no default value has been set. Of course, DDL generation is a feature that many people do not use in production (but many take the generated code as a template).
If you hand-write your DDL and actually used SERIAL, then using GenerationType.SEQUENCE may even conflict with the database behaviour. The correct way to map Hibernate with Postgres’ preferred ID strategy is using GenerationType.IDENTITY. Incidentally, the code is also much shorter and more readable:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
In PostgreSQL auto-increment is handled using the SERIAL pseudo type. You use this type when you execute CREATE TABLE.
Now to the point - this SERIAL pseudo type creates a sequence.
Autoincrement in PostgreSQL is handled using the created sequence. The default value of the id column becomes - nextval('your_sequence_name').
In Hibernate for an User entity:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users_seq_gen")
#SequenceGenerator(name = "users_seq_gen", sequenceName = "users_id_seq")
public Long getId() {
return id;
}
Read here:
http://www.postgresql.org/docs/8.4/static/datatype-numeric.html#DATATYPE-SERIAL
http://www.neilconway.org/docs/sequences/

Hibernate duplicate primary key on restart using GenerationType.TABLE

We're running into an issue where we have Event subclasses that use GenerationType.TABLE to generate the primary key, and when we restart the servers we are getting duplicate primary key errors.
We're using SQL Server and Hibernate version 3.5.1-Final.
Here's what our Hibernate annotations look like:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Event {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long eventID;
we don't specify the allocationSize so we're using the default value. The hibernate sequences table does increment but it seems like on restarts it's reusing already used ID's.
Try GenerationType.AUTO or SEQUENCE.
AUTO may work via hibernate magic, but SEQUENCE should create, funnily enough, a sequence in the database which it will use to get unique IDs.
Which SQL Server are you using?

Categories