allocationSize and duplicated pk issue - oracle

Jboss 7.2.0, ejb3, oracle
All entities in the project have defined sequence generator like
#SequenceGenerator(name="xx", sequenceName="yy" allocationSize="10")
For one-to-many relation sometimes I have issue with duplicated primary key. Not sure what is wrong here but after the transaction is rollback the sequence is reset and I've constraint violation errors all the time
I've changed allocationSize to 1 and it seems to be ok but what's reason ?

see the discussion: https://developer.jboss.org/thread/104030?start=15&tstart=0
in your question is not clear the sequenceName is it a hibernate_sequence or oracle sequence? if it's oracle - you shouldn't have duplicates
#Id(generate = GeneratorType.SEQUENCE, generator = "mysequence")
#SequenceGenerator(name = "mysequence", sequenceName = "MY_SEQ",allocationSize=1)
//#SequenceGenerator(name = "mysequence", sequenceName = "hibernate_sequence")
#Column(name = "COVT_ID", primaryKey=true)
public long getId() {
return m_id;
}

Probably, you used ddl-generation property with the value "drop-create-tables" property in your persistence.xml. This cause all sequences and tables to be dropped and recreated with the initial values again and so, the same sequence values are reused.

Related

spring data jpa + unwanted unique key generation

I am using spring data jpa for creation of my tables. My Requirement.
I have two Tables.
Basket Table - It has one to many Relationship with the Item table. A basket can have many Items.
Item Table - Here an Item can be associated with many Baskets.
I am using IGNORE_ROW_ON_DUPKEY_INDEX to make sure that the same combination of basketId and itemId, does not get persisted
So there is a mapping table in between in which holds the mapping of baskets and items. Now, in this table, i want the combination of basketId and itemId to be unique. Below is my entity stucture.
#Entity
Class Basket{
#Id
private long basketId;
...
#OneToMany(cascade = {CascadeType.Merge, CascadeType.DETACH, CascadeType.REFRESH})
#JoinTable(
name= "mapping_table",
joinColumns = #JoinColumn(name ='basketId'),
inverseJoinColumns = #JoinColumn(name ='itemId'),
indexes = {#Index(name = "my_index", columnList = "basketId, itemId", unique = true)}
#SQLInsert(sql = "INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX (mapping_table, my_index) */ INTO mapping_table(basketId, itemId) values (?,?)")
private List<Item> itemList;
...
}
#Entity
Class Item{
#Id
private long itemId;
}
my_index with the combination of both the keys are getting created, as expected in the mapping_table
Problem 1:
In the mapping_table, for some wierd reason, a new unique constraint with only itemId is created. Due to this unique key constraint, i am not able to persist rows where an item is associated with multiple baskets. As i said, i want the combination of both the keys to be unique and i am achieving this by creating the index (my_index)
Problem 2:
Why is basketId (which is also Identifier) in the basketTable not marked as unique in the mapping table. This not a problem but more of a question. Becuase itemId which is identifier in the item table has unique key constraint in the mapping table.
Solution :
I create the tables using spring data jpa, login to the db manually and drop the unique key constraint and the persist. But this is not possible in Production
Question
I want to do alter table to drop the constraint first before the persist thing happens. How to do that.
P.S, As you can see, I have imagined these tables and have not put the names of the actual table. Not withstanding the made up table names, the problem statement is accurate. I am using Oracle as target DB
Try to use a Set instead of a List, JPA should generated the correct schema with the correct constraints.

SpringBoot2 data JPA throwing ConstraintViolationException

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;

How to get DB sequence value when using micronaut-data with JDBC

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

Returned entity ID is different from the actual data saved in the database

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.

GenerationType.SEQUENCE generates ID's which are already existing

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.

Resources