I need a help on persisting an entity in a Oracle DB table that uses trigger and sequence for PK.
By now, I tried these from other stackoverflow questions:
#Id
#GeneratedValue(generator="increment")
#GenericGenerator(name="increment", strategy="increment")
This approach works. It finds the max value of PK and increment the value in 1. But, this doesn't update the Db sequence causing "constraint violation" error at some point.
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_sequence")
#SequenceGenerator(name="id_sequence", sequenceName="MY_DB_SEQ")
This approach doesn't work for me either. Sadly, the Db sequence is not accessible and causing error when it is trying to run internally "select MY_DB_SEQ.nextval from dual". Why is not accesible? Go and ask DB admin :)
It looks like the only option I have is passing null in the Entity PK attribute so that the DB trigger, which uses the a DB sequence to get the nextval when the ID is null, assigns the PK value in DB record.
How can I pass a null value for #Id? Of course this is throwing error because is needed. Is there any other annotation I can use for this?
If this is not possible, what other ways I should try?
Thanks for your help.
UPDATE
I couldn't find another way for this, having a DB Seq that is not accessible for user, and when it requires to pass NULL to PK in order to have DB use the trigger which check NULL value in PK to run seq nexval.
After granting access to DB Seq, this approach of course works.
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_sequence")
#SequenceGenerator(name="id_sequence", sequenceName="MY_DB_SEQ")
Did you create the sequence in the database as below?
CREATE SEQUENCE id_seq INCREMENT BY 1 START WITH 0 MINVALUE 0 MAXVALUE 100 NOCYCLE NOCACHE;
if not create first.
or else add the below properties in the application but it's not good practice.
spring.jpa.hibernate.ddl-auto = update
As of now, I couldn't find any solution to pass NULL to PK in Entity.
In DB, the DB Sequences were granted access. Spring Boot can now read the sequence and gran the next value.
Related
I'm trying to auto-generate ID's for my entity, but it's not generating. Instead, it's starting from 1 when there already exists an entry with id "1" in my DB. Why is it not generating id "9" for my new entity?
Typically when creating a table with GenerationType.IDENTITY on postgres, Hibernate will setup the id column plus a database sequence to manage this id.
By convention the sequence name will be "tablename_id_seq". E.g., for the table ad_group_action there will be a corresponding sequence ad_group_action_id_seq. You can connect to the database to double-check the actual sequence name created.
The sequence just starts from 1 and increments each time a row is inserted by Hibernate.
But if there are pre-existing rows -- or if rows with existing IDs are inserted "manually" into the table -- those rows can conflict with the sequence.
One solution is to simply reset the sequence (from pgAdmin or another database client) to start at a higher number (say 100), using something like:
ALTER SEQUENCE ad_group_action_id_seq RESTART WITH 100;
Now Hibernate will not conflict with the existing rows (assuming their max id is < 100).
Alternatively, when inserting rows manually, omit the id column and let postgres automatically set them. This way the table and the sequence will always be in sync.
I have an app where I want to save some entities which have some fields. I used liquibase to add some when the application starts. The problem is that when I try to save a new one Hibernate tries to give to it the id 1 but this id already exists in the database. How can I make hibernate aware of liquibase inserts?
It depends what is your ID generation strategy. If you are using a sequence simply set the initial value of the sequence to 10,000. This will allow you to insert up to 10,000 records with Liquibase.
For example if you are using PotgreSQL you can do
ALTER SEQUENCE sequence_name
MINVALUE 10000
START 10000
RESTART 10000;
Let's say I'm creating a record that has an id of 2. After I deleted that record and I create a new record, the id is 3. I would like it to be 2, since the old one with 2 is gone anyway. How? Or is this not smart to do.
Btw, the id column is a NOT NULL AUTO_INCREMENT
Thanks!
I don't think its a good idea, but still you can use this
If you're using MySQL as your database:
ALTER TABLE table_name AUTO_INCREMENT = 1
this will reset your auto increment column back to 1 or in your case.
you can refer to this documentation if ever.
How to create unique id in cassandra column families( like auto-increment id in mysql database ) ?
For unique IDs in Cassandra, you'll want to use UUIDs, which are probabilistically (nearly) guaranteed to be unique. There are a few built-in functions in CQL to help with UUIDs.
You asked for simple query to create table with uuid, so there you are:
create:
CREATE TABLE event (uuid uuid, name varchar);
insert:
INSERT INTO event(uuid, name) values(uuid(), 'john');
select:
SELECT * FROM event LIMIT 1;
to select on name column you must add new index:
CREATE index idx_event_name ON event(name);
and now you can select with where:
SELECT * FROM event WHERE name = 'john';
If you really need integer autoincrement IDs I've written a simple python module that does that after going through stackoverflow and not seeing anything decent that does that specific function. If you don't care about the ID being an integer you're better off using something like UUID which is probably safer and more elegant.
link: https://github.com/qdatum/globalcounter
I've Table uses Trigger and sequence to set its PK column.
The Hibernate mapping strategy for its Pk is assigned..
This yields in session.save(obj) returns object with id=0
How to make it returns the correct assigned PK value.
session.getIdentifier() doesn't work!
assigned means: Nobody generates the ID, the ID is set explicitely in the entity before persisting it.
What you want to do is impossible. Hibernate would have to insert an entity without knowing its ID, then the database would generate the ID, and Hibernate would have to reload the entity from the database to know its ID. But how would it reload the entity without knowing its ID?
The native generator does the same thing, and it works because the database provides a getLastGeneratedId() method which allows getting the IOD that the database has generated. But you can't do that with Oracle and a trigger.
Remove the trigger from the database, use the sequence generator, and everything will be fine.