JOOQ not saving changed unique key - java

I have a MySQL database storing values, and using JOOQ to interact with that data. Everything has worked fine for me, until I tried to change the value of a unique key. I have a table that stores groups that people can create, the owner of the group is stored as ownerid. I have ownerid set to be unique since each person can only own 1 group. The problem comes in when I try to change the ownerid (user passes ownership to another user). I set the new ownerid using record.setOwnerId(), and then I call record.store(). Once record.store() has completed, I am calling record.getOwnerId() and it is returning the correct (new) id. I should also note that there is no SQL errors that occur when this happens. The issue though, is that the SQL database never gets updated with the new value. When I do record.refresh(), the ownerid is set back to the previous value. Any idea why this would happen or how I would debug it? I should point out that I have verified that the new ownerid is not already in the table, and there doesn't appear to be any SQL errors being thrown.
Edit: It works completely fine if I modify the value manually, but for some reason record.store() refuses to change it

Related

MYSQL Workbench - indexes after delete (Java)

I have a problem with MYSQL Workbench. Let's say I have this table, the user 'x' has index 8. Let's say I delete this user, so now I have only 7 users. If I create a new user with Java Console, the new user will be created with ID 9 because it's in auto increment. Is there a way to tell Workbench to start from where it is the last number? in that specific case, start creating the new user from 8 and not 9?
I tried to check everywhere on the web, but found only some query to recreate the table, but its not what I want because I have some foreign keys linked to that table, so I can't just delete the table and recreate another one.
I'm not familiar with MYSQL Workbench, but I think you might be able to alter your table and to change the value of the AUTO_INCREMENT.
Here's a link that talk about it in more details and even has an example:https://www.w3schools.com/mysql/mysql_autoincrement.asp
I hope this help you.
There is not a way to do that. Using Auto Increment or Identity makes a value no longer usable once it is used.
So a user with an ID of 1 will always have an ID of 1. A possible workaround is to not delete users, but instead put in a column of TinyInt(1) labeled 'Deleted'
New Users will have Deleted set to 0. When a user is deleted, their record gets set to 1. It will keep your IDs in order and then you just need to account for querying users who are not deleted.

Does having a custom update query with WHERE clause gives more performance while updating in Spring Data JPA?

Let's say I have an entity called Car . Now the entity's primary key is not an auto generated Id. Lets say I need to update my car entity with a set of values.But the problem is I am having a requirement of ensuring the given Id is already existing in the database. Because I know in spring Data JPA we use the save() method to both save and update an existing entity.
Then in a case of inserting a new primary key for the save() method will lead to a save otherwise it will update that specific entity.So I always need to ensure during the update that the method will not create new entities for invalid ids.
So to overcome this issue I have seen many developers use a find() method call before the updation to ensure the given primary key is already existing.But you can see there will be an additional database hit to ensure that.
So to overcome this issue I thought of going with a custom update query.Then I can determine if the query is executed or not by declaring it's return type as int in the JPARepository. So according to my knowledge query will output 1 for success and 0 for a failed updation.
So what I need to know is, in the case of providing a not existing primary key for the method updateCar() can I always ensure that the update doesn't succeed because of that invalid primary key. I mean what happens if the update fails due to a different error?
The ultimate goal of this discussion is to avoid the check of the existence of the primary key before the updation. So if there any better approach please state it.
Ex:
#Modifying
#Query("UPDATE Car c SET c.status =:status WHERE c.id =:id")
int updateCar(#Param("status") String status, #Param("id") String id);
The int you get back from the update is the number of rows updated.
So what I need to know is, in the case of providing a not existing
primary key for the method updateCar() can I always ensure that the
update doesn't succeed because of that invalid primary key. I mean
what happens if the update fails due to a different error?
If the update fails for any other reason then you will get an Exception.
The problem with your solution is that you will have to write update statements for every use case.

How to UPDATE item only if cached value is not older than the current one

I have a generic java multi-user client server CRUD system where each user gets all items via SELECT, adds new items via INSERT, removes existing items via DELETE and modifies existing items via UPDATE.
All tables contain date_last_modified TIMESTAMPTZ and user_last_modified INTEGER REFERENCES users(id) columns.
I want to prevent a situation when at first each user SELECTs all items and then several users modify similar item and each subsequent UPDATE overwrites previous data.
I am trying to create an UPDATE query that compares date_last_modified value on client and on server and abort query if values are not equal (meaning someone had already modified it).
If another approach exists to handle a situation when a cached item is older then the one in DB then you are welcome.
I think that your approach is good but maybe you can implement it using a trigger before update
Your approach is ok but you can avoid aborting query (and also avoid querying timestamp beforehand in transaction for comparing the values) by adding date_last_modified to
UPDATE ... WHERE ... AND date_last_modified = ?
If the timestamp does not match no rows are updated.
Statement.executeUpdate(...) returns the number of updated rows. If it is 0 you can notify user about the race condition (and rollback transaction if needed).
You can also add a column serial update_count for this purpose. However, timestampz is ok if the value is changed on every update.

Creating empty objects in db or saving them later

I have the following table in my db:
CREATE TABLE document (
id INT PRIMARY KEY AUTOINCREMENT,
productModelId INT NOT NULL,
comment VARCHAR(50),
CONSTRAINT FK_product_model FOREIGN KEY (productModelId) REFERENCES product_model(id),
)
Of course, real table is much more complicated, but this is enough to understand the problem.
Our users want to see the number of the document when they click button "new". So, in order to do that, we have to create object in db and send to client that object. But, there is a problem. We need to know productModelId before we save the object in db. Otherwise we will have an sql exception.
I see two possible variants (both are ugly, really):
To show modal list with product models to user and after that create object in database with productModelId chosen by user.
To create a temporary number and after that to save the object in db when user finishes editing the document and saves id. We also need to remove NOT NULL case and validate this somwhere in code.
The first way is bad because we have too much modals in our application. Our UI is too heavy with them.
The second variant is ugly because our database is not consistent without all the checks.
What can you suggest we do? Any new solutions? What do you do in your apps? May be some UI tips. We are using the first variant at the moment.
Theory says that the id you use on your database should not be a relevant information, so the user should not see it if not well hidden in an URL or similar, so you should not display it to the user, and the problem you have is one possible confirmation of this theory.
Right now the solution you have is partially correct: it satisfies technical requirements, but is still bad because if the user doesn't complete the insert you'll end up with the DB having empty records (meaning, with ID and foreign key ok, but all other fields empty or with useless default values), so you are basically circumventing the database validations.
There are two better solutions, but both require you to review your database.
The first is not to use the id as something to display to the user. Use another column, with another "id", declare it unique on the database, generate it at application, display it to the user, and then use this other "id" (if it's unique, it is effectively an id) wherever needed.
The second one is the one that is being used often cause it does not require a central database or other authority to check uniqueness of ids, so scales better in distributed environments.
Drop the use of the common "id int" auto-incremented or not, and use UUIDs. Your id will be a varchar or a binary, an UUID implementation (like java.util.UUID, but you can find in other languages) will generate a unique id by itself whenever (and wherever, even on the client for example) you need it, and then you supply this id when saving.
We make it the following way.
Created table id_requests with fields issue_type_id and lastId. We need this in order to avoid the situation when two users hit the button 'new' and get the same ids.
And of course we added field innerNum to all the tables we use this feature in.
Thank you!

Android/ORMLite Insert Row with ID

I'm currently using ORMLite to work with a SQLite database on Android. As part of this I am downloading a bunch of data from a backend server and I'd like to have this data added to the SQLite database in the exact same format it is on the backend server (ie the IDs are the same, etc).
So, my question to you is if I populate my database entry object (we'll call it Equipment), including Equipment's generatedId/primary key field via setId(), and I then run a DAO.create() with that Equipment entry will that ID be saved correctly? I tried it this way and it seems to me that this was not the case. If that is the case I will try again and look for other problems, but with the first few passes over the code I was not able to find one. So essentially, if I call DAO.create() on a database object with an ID set will that ID be sent to the database and if it is not, how can I insert a row with a primary key value already filled out?
Thanks!
#Femi is correct that an object can either be a generated-id or an id, but not both. The issue is more than how ORMLite stores the object but it also has to match the schema that the database was generated with.
ORMLite supports a allowGeneratedIdInsert=true option to #DatabaseField annotation that allows this behavior. This is not supported by some database types (Derby for example) but works under Android/SQLite.
For posterity, you can also create 2 objects that share the same table -- one with a generated-id and one without. Then you can insert using the generated-id Dao to get that behavior and the other Dao to take the id value set by the caller. Here's another answer talking about that. The issue for you sounds like that this will create a lot of of extra DAOs.
The only other solution is to not use the id for your purposes. Let the database generate the id and then have an additional field that you use that is set externally for your purposes. Forcing the database-id in certain circumstances seems to me to be a bad pattern.
From http://ormlite.com/docs/generated-id:
Boolean whether the field is an auto-generated id field. Default is false. Only one field can have this set in a class. This tells the database to auto-generate a corresponding id for every row inserted. When an object with a generated-id is created using the Dao.create() method, the database will generate an id for the row which will be returned and set in the object by the create method. Some databases require sequences for generated ids in which case the sequence name will be auto-generated. To specify the name of the sequence use generatedIdSequence. Only one of this, id, and generatedIdSequence can be specified.
You must use either generatedId (in which case it appears all ids must be generated) or id (in which case you can set them) but not both.

Categories