I need a simple sequence which would give me incremented integers that I later on use as part of a String.
I made this sequence using postgresql command line:
CREATE SEQUENCE my_seq
INCREMENT BY 1
The sequence exists as I can query it from postgresql command line, But I'm trying to get the values using hibernate:
Query query = session.createSQLQuery("select nextval(:sequence);");
query.setParameter("sequence", "my_seq");
Long nextVal=((BigInteger)query.uniqueResult()).longValue();
And I am getting this exception:
ERROR: relation "my_seq" does not exist
The sequence values do NOT represent the attribute of any entity. I only need them to store the number of logins, but I do not store the logins as entities.
EDIT: I got it working by adding the scheme name to the query:
String query1 = "select nextval(myscheme.my_seq)";
Query query = session.createSQLQuery(query1);
I can't figure out why it needed the scheme though, as myscheme was already default and all other queries worked fine without specifying the scheme. If anyone can shed some light I shall accept its answer.
You don't need to map a sequence to an entity.
Just leave the mapping as follow for the ID column of your entity, and the id of the tntity will be generated from the sequence my_seq. You don't need to call nextval(my_seq) or anything else.
#Entity("myEntity")
public class MyEntity {
#Id
#Column(name = "id", unique = true, nullable = false, insertable=false)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq")
#SequenceGenerator(name = "my_seq", sequenceName = "my_seq", allocationSize = 1)
private long id;
}
Below is the logic which will use a sequence called "my_seq" from the database and map it to the column "column_name" table "table_name"
Soon after you import the classes the sequence generator should be placed before you begin the class
#Entity
#org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
#Table(name = "table_name")
#SequenceGenerator(name = "my_seq", sequenceName = "my_seq")
public class ClassName implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "my_seq")
#Column(name = "column_name")
private Long columnName;
}
Let me know if this is useful.
In order to avoid hardcoding schema to your query, you can set hibernate.default_schema property in your persistence.xml as follows.
<property name="hibernate.default_schema" value="myscheme"/>
This could be also used in spring configuration file as is stated here.
Related
Info: Oracle DB 19. Hibernate is v5.5.4 with org.hibernate.dialect.Oracle12cDialect. JDBC driver is v12.2.0.1.
Question:
I want to save an entity with JPA/Hibernate (DB is Oracle 11g), that has an autogenerated ID column (here: PROT_ID).
CREATE TABLE SOME_PROTOCOL(
PROT_ID NUMBER(18) GENERATED ALWAYS AS IDENTITY (START WITH 123 MAXVALUE 99999) NOT NULL,
MORE_COLS VARCHAR2(500 CHAR) NOT NULL);
To add a new record, I have to skip the ID column, like that:
insert into SOME_PROTOCOL (MORE_COLS) values ('Some Value');
This is my Entity class:
#Entity
#Table(name = "SOME_PROTOCOL")
public class SomeProtocol {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROT_ID", insertable = false)
private Long id;
// Getter, Setter, other columns
}
Saving the entity with
SomeProtocol s = new SomeProtocol();
s.setMoreCols("whatever");
hibernateSession.save(s);
leads to this error:
ERROR: Invalid argument(s) in call
Hibernate: insert into APPL_PROTOCOL (PROT_ID, MORE_COLS) values (default, ?)
Ok, JPA doesn't skip the ID column, but sets default as a value.
I tried some more with #Column(insertable=false) or GenerationType.AUTO, but to no avail.
How can I save an entity class with an autogenerated ID column?
Solution:
We changed the ID generation for that table, we now use an external sequence (previously it was auto-generated). Hibernate can save the entity now via hibernateSession.save.
#SequenceGenerator(name = "SEQ_APPL_PROT_GENERATOR", sequenceName = "SEQ_APPL_PROTOCOL_ID", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_APPL_PROT_GENERATOR")
#Column(name = "PROT_ID")
private Long id;
I think the insertable = false in your #Column annotation might be the problem. Please try without that and let us know how that works.
You can read more about this attribute on Please explain about insertable=false and updatable=false in reference to the JPA #Column annotation.
I am trying to set up table entities with primary key id's generated from sequences I previously defined and used in an Oracle DB.
I am trying to use the Sequence Generator and Generated Value annotations but they don't seem to work quite right for me. I'm unsure what I am missing/doing wrong.
#Id
#Column(name = "ID")
#GeneratedValue(Strategy=GenerationType.SEQUENCE, generator = "seq")
#SequenceGenerator(name="seq", sequenceName = "id_seq", allocationSize = 1)
private long id;
This does not seem to work. Any advice on how to solve this problem, or a usable workaround, would be appreciated. This uses an Oracle 11 DB and JPA 2.
This is an example, working with JPA 2.0, of how to get an id from an Oracle sequence.
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_JPA_ID_GENERATOR")
#SequenceGenerator(name = "MY_JPA_ID_GENERATOR", allocationSize = 1, sequenceName = "MY_ORACLE_SEQUENCE_NAME")
#Column(name = "ID", unique = true, nullable = false, updatable = false)
private Long ID;
(Hibernate 5, PostgreSQL 9.6, Java 8, Spring ORM 4.3.6)
The following entity class Car worked fine:
import javax.persistence.*;
#Entity
#SequenceGenerator(name = "carSequence", sequenceName = "car_id_seq", )
#Table(name = "car")
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "carSequence")
private Long id;
//...
}
It is based on the following SQL (simplified):
CREATE TABLE car (id bigint NOT NULL);
ALTER TABLE car ADD CONSTRAINT PK_car PRIMARY KEY (id);
However, I got this warning which I wanted to solve:
WARN org.hibernate.orm.deprecation: HHH90000014: Found use of deprecated [org.hibernate.id.SequenceHiLoGenerator] sequence-based id generator; use org.hibernate.id.enhanced.SequenceStyleGenerator instead. See Hibernate Domain Model Mapping Guide for details.
So, I replaced the old Car with:
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
#GenericGenerator(
name = "carSequence",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
#org.hibernate.annotations.Parameter(name = "sequence_name", value = "car_id_seq"),
#org.hibernate.annotations.Parameter(name = "initial_value", value = "1"),
#org.hibernate.annotations.Parameter(name = "increment_size", value = "50")
}
)
#Table(name = "car")
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "carSequence")
private Long id;
//...
}
However, then I got error's in my code:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "pk_car"
Detail: Key (id)=(-34) already exists.
Strange thing: -34 seems odd.
Other strange thing: sequence generates duplicate keys.
The table of cars is already filled up until id = 709.
On the sequence definition, curval = 15, nextval = 16 and increment = 1.
You're not specifiying the optimizer to use.
In your first variant you're using the SequenceHiLoGenerator, in the second variant you only specify the increment-size without setting the optimizer to HiLo.
According to docs (SequenceStyleGenerator) Hibernate chooses a generator itself if not specified. Because increment_size is > 1 (see here) Hibernate probably selects the pooled-lo optimizer wich operates differently to seqHiLo.
So, you should add
#Parameter(name = "optimizer", value = "hilo"),
to your Parameters to set the optimizer explizitly to seqhilo
I have an entity class with below primary key generation strategy
#Id
#Column(name = "id", nullable = false)
#TableGenerator(name = "USERGENERATOR", table = "my_sequences", pkColumnName = "sequence_name", pkColumnValue = "user_id", valueColumnName = "next_value")
#GeneratedValue(strategy = GenerationType.TABLE, generator = "USERGENERATOR")
protected Integer id;
This was working fine until a new requirement came up where I need to insert a new row using a native query. The primary key column doesn't use auto_increment because of Entity Inheritance strategy (#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)) in place.
I was wondering if there is a way to ask the table generator for the next value using the EntityManager.
I don't think you can access the #TableGenerator through any public API, but getting the next value with native SQL is easy. Just use these two queries:
-- get the current value
select next_value from my_sequences where sequence_name = 'user_id';
-- update value
update my_sequences set next_value = next_value + 1;
There is a risk of conflict if #TableGenerator fetches the next value at the same time.
You need to change your #GeneratedValue(strategy = GenerationType.TABLE, generator = "USERGENERATOR") by #GeneratedValue(strategy = GenerationType.IDENTITY) like this when you add a new element, it will add 1 auto
My code :
#Id
#Column(name = "cust_admin_id" )
#SequenceGenerator(name = "Cust_Admin_seq" , sequenceName = "cust_Admin_id",allocationSize=1)
#GeneratedValue(strategy = GenerationType.SEQUENCE , generator = "Cust_Admin_seq")
private Integer custAdminId;
Please help as this is in production...
you violate a constraint.
f.e. you insert the same dataset twice (same primary key, maybe different values) or you insert a dataset, that has no foreign key dataset connected to another table.
We need a bit more information