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
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.
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
#SequenceGenerator(name = "generator", schema = "MD", sequenceName = "sq_base_class")
public Long getId() {
return id;
}
Hi! I have entity which using MS SQL Sequence for generating ID, but value is incorrect.
com.microsoft.sqlserver.jdbc.SQLServerException: Violation of PRIMARY KEY constraint 'PK_BCL'. Cannot insert duplicate key in object 'MD.BASE_CLASS'. The duplicate key value is (551009).
Example: SequenceGenerator set ID = 551009, but select next value for md.sq_base_class return 551115. How to resolve it?
Hibernate-version: 5.3.10.Final
Maybe you lost the allocation size = 1 in #SequenceGenerator
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;
I'm using H2 for testing environment my app. I have table Order and i would like start order id from 10000. I created Table Column:
#Id
#TableGenerator(name = "ORDER_GEN",
table = "ID_GEN",
pkColumnName = "SEQ_NAME",
valueColumnName = "SEQ_NUMBER",
pkColumnValue = "ORDER_GEN",
initialValue = 1000)
#GeneratedValue(strategy = GenerationType.TABLE, generator = "ORDER_GEN")
private Long orderId;
but doesn't work. I restarted app, table ID_GEN was created but order each time starting from 0.
Any ideas ?
Regards
I found solution here:
https://stackoverflow.com/a/13315956/5877109
The problem is with hibernate bug.
After added setting to application.properties:
spring.jpa.hibernate.use-new-id-generator-mappings=true
everything works very well.
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.