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;
Related
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.
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.
I'm getting an Oracle error / org.hibernate.exception.SQLGrammarException when I run a JUnit test against a Java class which uses JPA and Spring:
ORA-00904: "ALIAS"."COLUMN_NAME": invalid identifier
The odd thing is that the JUnit test works when run against a development database but fails when run against a database which I use for Continuous Integration builds (they are both Oracle databases).
Therefore, this would suggest that there's something missing or awry in the latter d/b. However, I have double- (and triple-)checked that the table referred to is identical in both databases and contains the column COLUMN_NAME that the error is referring to.
Further information - the DAO Java class invoked in the JUnit test uses a javax.persistence.EntityManager:
MyClass myObject = entityManager.find(MyClass.class, idNumber);
The MyClass JPA entity class maps onto the Oracle table:
#Configurable
#Entity
#Table(name = "MyTable", schema = "MySchema")
public class MyClass implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_SEQ")
#SequenceGenerator(name = "MY_SEQ", sequenceName = "MY_SEQ", allocationSize = 1)
#Column(name = "ID")
protected BigDecimal id;
#Column(name = "COLUMN_NAME")
private String columnName;
...
}
The column COLUMN_NAME in the database table in both databases is VARCHAR2(50) and nullable.
Versions:
Java - 1.6
Spring - 3.1.1
Oracle - 11.2.0.3.0
Thanks in advance for any assistance.
Found the problem. I found the query that Hibernate was creating (by adding
<property name="hibernate.show_sql" value="true" />
to my data-persistence.xml file) and tried to run it in the database where the test was failing. It transpires that in the entity Java class, the associated database table is defined like this:
#Table(name = "MyTable", schema = "MySchema")
... which works fine against the development d/b. However, the continuous integration database has all the tables created in a schema called something else, hence the error.
Thanks to everyone for their help.
Had the same issue. The reason was I missed adding the schema and the table name.
#Table(name = "Table", schema = "Schema")
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/
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?