Hibernate and Oracle: Primary Key constraint violation - java

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").

Related

When using the #SequenceGenerator/#GeneratedValue in JPA - is a database trigger redundant/unnecessary?

I saw this post (JPA Entity Lifecycle Events vs database trigger), but it didn't ask quite as explicitly as I am here:
Am I required to have a sequence AND a trigger for when I insert a row with a PK with a value of (null)?
Or will JPA somehow interpret the sequence annotations as a signal to grab .nextVal?
If you define a sequence on your primary key (#Id annotated field) and you map the sequence using the annotations #GeneratedValue and #SequenceGenerator, you can persist an entity with a null primary key. JPA will automatically call the sequence to get the next value (or get it from its cache).
The primary key declaration should look like.
#Id
#Column(name = "TABLE_PK")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_GENERATOR_NAME")
#SequenceGenerator(name = "SEQUENCE_GENERATOR", sequenceName = "SEQUENCE_NAME")
private Integer id;

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 - how to set auto increment in both mysql and oracle databases?

I'm using hibernate with a MySQL database in my spring MVC project. I have used the #GeneratedValue annotation to set auto-incremenet on my id fields. So all my entities have this piece of code and everything is working as expected:
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
At this time, I want to switch to an Oracle database. Now, I have two questions here:
1. What's the best solution to set auto-increment field in oracle? I used this code, but is not working:
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_Sequence")
#SequenceGenerator(name="id_Sequence", allocationSize=1)
2(More important question). Is there any way to use a unique annotation to set auto-increment that will work for both MySQL and Oracle?
1:
If you define your own generator, your have to use the generator attribute in #GeneratedValue. And if you have created your own sequence you have to define the name with sequenceName otherwise hibernate will create one for you.
#SequenceGenerator(name="some_gen", sequenceName="Emp_Seq")
#GeneratedValue(generator="some_gen")
2:
The most flexible (and portable) way is to use the TABLE strategy
#GeneratedValue(strategy=GenerationType.TABLE)
or more explicit
#GeneratedValue(generator="some_gen")
#TableGenerator(name="some_gen",
table="ID_GEN",
pkColumnName="GEN_NAME",
valueColumnName="GEN_VAL")
This will generate (if schema generation is enabled) a table ID_GEN with the columns GEN_NAME, GEN_VALUE, if schema generation is not available you have to create this table on your own.
You find more complete information from hibernate docs here: http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch05.html#mapping-declaration-id-generator

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