Getting next ID as PK for table insert - java

I'm working on some old java code, and as part of an insert, the code makes a db call to get the last ID used in a table, then increments the ID, and uses the incremented ID as the next ID to use for the insert, as the PK.
It's a web application, and it seems to me that the same ID could be retrieved on a subsequent get ID call before the first/prior insert is done.
How would I prevent this, to ensure that the same ID is not reused?

Use a transaction in your sql code.

If you Database Server supports the Auto Increment attribute, then you can apply it to the ID column and it will assign itself incrementing unique IDs. The server does all the work and ensures that the ID is valid and unique.

Related

Cosmos SQL upsert not working as expected

If I try to upsert a document with an id and partition key that already exists, it works as expected IF there are no Unique constraints set on the container.
However, when I set any value in the table as Unique, then the upsert doesn't work and I get a (409 conflict - a Document with an id matching the id field of document already exists). The Unique constraint shouldn't be a problem in this case, but it causes this error, which has a strange error description for an upsert because it shouldn't matter if the id already exists.
I'm using documentClient.upsertDocument(collectionLink, documentDefinition, null, true);.
Cosmos DB's Upsert / Replace flow is based on the document's unique identifier (id and Partition Key value), Unique Fields are there to add extra checks for data validation.
When an Upsert operation is made, the service will look for an existing document with the same id and Partition Key value, if there is one, it will update it, otherwise, it will create it.
In your case, you are always sending a new random id, so Upsert is not finding an existing document to update and it's creating a new one every time.
Please define your own id before initiating the Upsert, and set the autogenerate id attribute in the upsert call to it's default (true) value: client.upsertDocument(collectionLink, documentDefinition).

Auto sequence incrementer at database

I'm new to programming, so need little help from you guys.
I created a simple registration from in HTML controlled by servlet using oracle.
Whenever i submit my record, it gets stored perfectly in database, but I have assigned ID for every stored record which is not appearing to be increment in ascending order even after assigning primary key to ID.
There is no short way to auto increment id in database itself. This post describes good way to do it in oracle.
How to create id with AUTO_INCREMENT on Oracle?
Use a database sequence. And increment it by 1 every time you take a new value from that DB sequence.

Hibernate: Insert back a deleted row with the same ID

My Use Case:
my Hibernate configuration using auto increment generator for insert and I don't want to change it.
A user deleted a object with ID:10 and I saved this deleted object to somewhere.
later on, user decide to restore this deleted object back with the same ID:10.
since this object with ID:10 has been deleted from the database, How can I use Hibernate to insert it back to database while the hibernate configuration using auto increment generator(remember: I need keep the same ID for this object in database)?
Thanks,
Alex
I doubt Hibernate will let you do it if you don't change the generator. What about inserting it and then updating it with direct SQL and invalidating any hibernate caches?
I doubt Hibernate will not allow you to do this. However you can go and write sql queries to update Tables [If you have used Table Generator] to change the current index position that can be used but it will hell of complicated logic since you will always have to keep track on which index record is not present

How can I treat a sequence value like a generated key?

Here is my situation and my constraints:
I am using Java 5, JDBC, and DB2 9.5
My database table contains a BIGINT value which represents the primary key. For various reasons that are too complicated to go into here, the way I insert records into the table is by executing an insert against a VIEW; an INSTEAD OF trigger retrieves the NEXT_VAL from a SEQUENCE and performs the INSERT into the target table.
I can change the triggers, but I cannot change the underlying table or the general approach of inserting through the view.
I want to retrieve the sequence value from JDBC as if it were a generated key.
Question: How can I get access to the value pulled from the SEQUENCE. Is there some message I can fire within DB2 to float this sequence value back to the JDBC driver?
Resolution:
I resorted to retrieving the PREVIOUS_VAL from the sequence in a separate JDBC call.
Have you looked at java.sql.Statement.getGeneratedKeys()? I wouldn't hold out much hope since you're doing something so unusual but you never know.
You should be able to do this using the FINAL TABLE syntax:
select * from final table (insert into yourview values (...) );
This will return the data after all triggers have been fired.

How do I ensure data consistency in this concurrent situation?

The problem is this:
I have multiple competing threads (100+) that need to access one database table
Each thread will pass a String name - where that name exists in the table, the database should return the id for the row, where the name doesn't already exist, the name should be inserted and the id returned.
There can only ever be one instance of name in the database - ie. name must be unique
How do I ensure that thread one doesn't insert name1 at the same time as thread two also tries to insert name1? In other words, how do I guarantee the uniqueness of name in a concurrent environment? This also needs to be as efficient as possible - this has the potential to be a serious bottleneck.
I am using MySQL and Java.
Thanks
Assuming there is a unique constraint on the name column, each insert will acquire a lock. Any thread that attempts to insert it a second time concurrently will wait until the 1st insert either succeeds or fails (tx commit or rolls back).
If the 1st transaction succeeds, 2nd transaction will fail with with a unique key violation. Then you know it exists already.
If there is one insert per transaction, it'ok. If there are more than 1 insert per transaction, you may deadlock.
Each thread will pass a String name -
where that name exists in the table,
the database should return the id for
the row, where the name doesn't
already exist, the name should be
inserted and the id returned.
So all in all, the algo is like this:
1 read row with name
2.1 if found, return row id
2.2 if not found, attempt to insert
2.2.1 if insert succeeds, return new row id
2.2.2 if insert fails with unique constraint violation
2.2.2.1 read row with name
2.2.2.2 read should succeed this time, so return row id
Because there can be a high contention on the unique index, the insert may block for some time. In which case the transaction may time out. Make some stress test, and tune the configuration until it works correctly with your load.
Also, you should check if you get a unique constraint violation exception or some other exception.
And again, this works only if there is one insert per transaction, otherwise it may deadlock.
Also, you can try to read the row at step 1 with "select * for update". In this case, it waits until a concurrent insert either commits or succeeds. This can slightly reduce the amount of error at step 2.2.2 due to the contention on the index.
Create a unique constraint on name column in database.
Add a unique constraint for the name column.

Categories

Resources