I'm using micronaut-data with JDBC in on my application(no hibernate)
I need to generate my primary key value using Oracle DB sequences
As per their official doc(https://micronaut-projects.github.io/micronaut-data/1.0.x/guide/#jdbc) Section:9.1.4.1 SQL Annotations
Only some of JPA annotations are supported and I didn't find #GeneratedValue and #SequenceGenerator in the list(So not sure whether these are supported or not)
Moreover the doc says,
Section 9.1.4.2 ID Generation
If you wish to use sequences for the ID you should invoke the SQL that generates the sequence value and assign it prior to calling save().
So, what would be the best way to query Oracle database to get sequence value ?(As I don't have any session/entity manager here unlike JPA).
Already tried generating sequence using JPA annotations:
#GeneratedValue and #SequenceGenerator
Also using,
#GenerateValue present in micronaut-data library
(io.micronaut.data.annotation.GeneratedValue)
Sample Code:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQ")
#SequenceGenerator(sequenceName = "EMPLOYEE_ID_SEQ", allocationSize = 1, name = "ID_SEQ")
private Long employeeId;
Above code failed with:
Caused by: java.lang.NullPointerException: null
at oracle.jdbc.driver.OraclePreparedStatement.setupDbaBindBuffers(OraclePreparedStatement.java:3194)
Sequence generators are not supported yet but are on the TODO list
Related
Hi all i have a weird problem with the generation of PK calling the jpa method save.
Here and exmpale of the snippet i have implemented:
Entity
#Table(name = "MYTABLE")
#Entity
public class EEMYTABLE{
#Id
#Column(name = "IDMYTABLE")
#GenericGenerator(name="generator" , strategy="increment")
#GeneratedValue(generator="generator")
private Long id;
...
Repository
public interface MyTableRepository JpaRepository<MYTABLE,Long> {}
Service
#Autowired
private MyTableRepository myTableRepository;
public void saveNewRecord() {
EEMYTABLE newRecord = new EEMYTABLE();
myTableRepository.save(newRecord);
Problem Steps:
i run save method from my local server. It's all ok.
i run the ssave method from my remote server. It fires the following excepion: " ORA-00001: unique constraint violated "
now if i run again the method from the server is all ok.
if i follow with another call from my local env i have the exception: " ORA-00001: unique constraint violated "
It seems that if i run the method in more than 1 env there is a desync in the internal spring generator value.
Someone with ideas to fix it?
I try some solutions read on internet but i ave not solved the problem.
The "increment" hibernate strategy is not suitable if you have several environments using the same database since it relies on incrementation of an integer inside the JVM.
This explains why your environments generate the same ids.
In your case, you have to rely on a database mechanism, e.g. sequences.
See Hibernate generator class increment vs sequence? for more details.
I am using Spring Boot 2 for creating microservices. I have a scenario to save an entity. In entity for Id column I have added like below
#Id
#GeneratedValue(Strategy=GenerationType.Auto, generator="increment")
#GenericGenerator(name="increment", strategy="increment")
#Column(name="Id", insertable=false)
private Integer id;
Above works sometimes and it throws Primary Key Constraint Violation Exception sometimes. It is not consistent though. I am running it as two instances with different ports.
Error I get is unique constraint violated:
ConstraintViolationException: could not execute statement; constraint [primary_key_cons]; nested exception is ConstraintViolationException.
Only option I have is to change the strategy to sequence.
Did you insert some data manually? Maybe hibernate is generating id values which are already existing in db. If you can, just clear that table and test it again
Don't use generic generator with strategy increment. It is not recommended to use in a cluster.
increment
generates identifiers of type long, short or int that are unique only when no other process is inserting data into the same table. Do not use in a cluster.
for more info - here
Use GenerationType.SEQUENCE and crate a SequenceGenerator.
Example,
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "YourSequenceGenerator")
#SequenceGenerator(sequenceName = "YourSequence", name = "YourSequenceGenerator", allocationSize = 1)
private Integer id;
developping a new Java Spring MVC microservice i have encountered a minor issue.
When i send a creation request for any entity, the id generated always follows the previous one.
My event entity id configuration
My user entity id configuration
For example, this is what i got from these 2 requests
User creation request (you can see the id value is 1)
Event creation request (you can see the id value is 2)
The created event Id is the last created user Id + 1 which i obviously do not want to happen.
I want separate Id values for each entity. I want to know what i am doing wrong.
Thank you
Your solution worker pretty well ;)
I finally used it and added #SequenceGenerator annotation to initialize the count at 0.
#SequenceGenerator(name = "seq", initialValue = 0)
public class ClassName {
#Id
#GeneratedValue(generator = "seq")
private Integer id;
}
Thank you very much Daniel, that's kind of you.
You are using #GeneratedValue without providing a strategy.
Therefore it uses the AUTO strategy by default which indicates that the persistence provider should pick an appropriate strategy for the particular database.
As both ID columns share the same name I assume that both entities share one and the same generator.
Which results in
Create event entity with ID = 1 as the generator started at one
Create user entity with ID = 1 + 1 as new generated value is requested
You should think about using different sequences for generating separate IDs for each entity.
Following uses a DB sequence to generate an ID
#Id
#GeneratedValue(generator = "my_entity_name_seq")
private long id;
If I would not specify a concrete generator in the annotation hibernate ,for example will, create a default sequence called hibernate_sequence which is then used for all entities which use #GeneratedValue without specifying a generator. This then leads to incremented values over all tables / entities.
I'm using Spring Data JPA. When I'm inspecting the Entity returned by the save(Entity) method, it is different from the actual ID saved in the database. I'm using Oracle and my Entity ID config is using sequence from Oracle db.
#Id
#Column(name = "ID", nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_NAME")
#SequenceGenerator(name = "SEQ_NAME", sequenceName = "SEQ_1", allocationSize = 1)
private BigDecimal id;
Example scenario:
Insert record1 using save(record1);
Inspected record1 to have ID = 1001
Checked the db and the ID is 1002.
All other data are OK except the ID.
EDIT:
I remove all other logic in the code and leave just the saving part to isolate the issue.
I just found out that there's a db trigger that calls the SEQ1.nextVal every time a record is getting inserted. Dropping the trigger and altering the table to have DEFAULT SEQ1.nextVal solves my problem.
I have a spring boot application which is already running online for several months without any problems until today. I have a Entity with id generation type sequence:
#Entity
#ComponentScan
public class MyEntity {
/**
*
*/
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
}
Since today im getting errors when a new entity is created and stored:
Unique index or primary key violation: "PRIMARY_KEY_D92 ON PUBLIC.MyEntity(ID) VALUES (3713, 250)"; SQL statement:
Everytime when this error occurs the generated id (3713 in this case) is already existing in the database. So why all of a sudden the GenerationType.SEQUENCE is generating ids which are already existing?
EDIT
I use the H2 Database version 1.4.191
I've encountered this problem with Hibernate, but we had explicit #SequenceGenerator annotations. The problem is that the default SequenceGenerator in JPA has an allocationSize of 50, where as the default database sequence increments by 1. Those two values need to be the same. One solution is to define your SequenceGenerator and explicitly set that allocationSize.
#SequenceGenerator(name = "my_entity_gen", sequenceName = "my_entity_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_entity_gen")
Generators must be unique, unless you want two tables to share them.
The other solution is to use a different generation strategy.
#GeneratedValue(strategy = GenerationType.IDENTITY)
This works if the database already knows to query the sequence upon inserting, as they usually do, unless you've explicitly created the sequence after the table.
The first approach will trigger two queries to the database for every insert, so it's almost certainly less efficient.