How to Prevent Multiple entries stored in database? - java

Consider am using java , struts, hibernate and oracle. How can i prevent duplicate entries stored in database. One way is to make field as Unique . For example i am entering country "USA" in jsp page,USA is already available means how can i prevent it. Please let me know.
Regards,
sara

You should always indeed put a unique constraint on fields which must stay unique. This will, however, lead to a cryptic exception at commit time. If you want to be more user-friendly, you should check if the entry already exists (using a query) before inserting it, and display a useful and readable error message to the user if the entry already exists.
This still allows two concurrent users to check at the same time, then insert at the same time, but it greatly reduces the probability, and the unique constraint makes sure that one of the commits will fail, leaving your database in a consistent state.

Query your database whether it already contains USA or not. If it does, then don't store it. If not, then do.

Add a unique index to your database table on the country column.
Additionally you can annotate the country attribute of your hibernate object with #Column(unique=true).

Related

How to redistribute unique integer ids in a MySQL database?

Consider this:
I have a database with 10 rows.
Each row has a unique id (int) paired with some value e.g. name (varchar).
These ids are incremented from 1 to 10.
I delete 2 of the records - 2 and 8.
I add 2 more records 11 and 12.
Questions:
Is there a good way to redistribute unique ids in this database so it would go from 1 to 10 again ?
Would this be considered bad practice ?
I ask this question, because after some use of this database: adding and deleting values the ids would differ significantly.
One way to approach this would be to just generate the row numbers you want at the time you actually query, something like this:
SET #rn = 0;
SELECT
(#rn:=#rn + 1) AS rn, name
FROM yourTable;
ORDER BY id;
Generally speaking, you should not be worrying about the auto increment values which MySQL is assigning. MySQL will make sure that the values are unique without your intervention.
If you set the ID column to be primary key and an auto-increment as well, "resetting" is not really necessary because it will keep assigning unique IDs anyways.
If the thing that bothers you are the "gaps" among the existing values, then you might resort to "sort deletion", by employing the is_deleted column with bit/boolean values. Default value would be 0 (or b0), of course. In fact, soft-deleting is advised if there are some really important data that might be useful later on, especially if it involves possibility for payment-related entries where user can delete one of such entries either by omission or deliberately.
There is no simple way to employ the deletion where you simply remove one value and re-arrange the remaining IDs to retain the sequence. A workaround might be to do the following steps:
DELETE entry first. i.e. delete from <table> where ID = _value
INSERT INTO SELECT (without id column). please note that the table need to be identical in terms of columns and types in order for this query to work properly, so to speak... and you can also utilize temporary as the backup_table. i.e. insert into <backup_table> select <coluum1, column2, ...> from <table>
TRUNCATE your table, i.e. truncate table <table>
copy the values from the temp table back into the existing table. You can utilize the INSERT INTO SELECT once again, but make sure to drop the temp table in the end
Please note that I would NOT advise you to do this, mainly because most people utilize some sort of caching in their applications and they also utilize the specific ways to evaluate whether a specific object is the same.
I.e. in Java, the equals() and hashCode() methods for POJOs are overriden and programmers generally rely on IDs to be permanent way of identifying a specific object. By utilizing the above method, you essentially break the whole concept and I would not advise you to change the object's autoincrement ID value for this reason, before anything else.
Essentially, what you want to do is simply an anti-pattern and will generally make common patterns and practices employed by experienced programmers into solutions that are prone to unexpected issues and/or failures... and this especially applies if/when advanced features are involved, such as employing this such anti-pattern into an application that utilizes galera cluster and/or application caching.

How to make a mutual exclusive code section for database access?

Suppose that we want to insert a record in some table. But in order to be allowed to do that, that table must not contain any record with duplicated values in some fields in such a way that database primary keys are not enough for doing that control and it must be done by the application's code. If the code for inserting a record looked like this...
check duplicates
if no duplicates:
insert the record
else:
show the user a error
That code would be wrong because two different threads could make the check of duplicates at the same time, then pass the check, then insert the same record, producing a situation where there are duplications so that the table state is now inconsistent.
As the code is a web application made in Java, I guess that it would be enough to synchronize the critical section with the same static object so that any user that makes the execution flow to get into the critical section must wait for another one that has previously got into that section. But, is that enough? Is there a more elegant way for doing that?
You can use database triggers for that. The correct one to use in this case is "Before Insert" trigger. If the use case is simpler, another option would be to use checks and constraints.
Third option would be to do it in the java code and synchronizing the section like you described would work too.
According to the clarification from the question comments, a unique index is exactly what's needed here. Create a unique index with the name column as well as the boolean column in it. It will then not allow two entries where both columns have the same values.

JDBC template: how to properly handle insert if not exists [duplicate]

This question already has answers here:
SQL Server Insert if not exists
(13 answers)
Closed 8 years ago.
I have a table users with primary key column email.
I have a piece of code where I store the user that simply invokes userDao.store(user);
Since the constraint exists, I can catch the exception and show the error on the UI. This approach works fine.
Another solution is to check first if the user exists and then store him in the database. This would result in two consecutive queries - select and then insert. So basically if the user exists I show the error. The issue I see here that if two users with the same email try to register at the same time and provide the same email. It may happen than both threads check the existence of the user and return nothing. Then the first thread saves the user and the second throws exception.
The third approach is to use MERGE query (I use hsqldb). Basically in one query I insert the user only if he does not exist. Then I can see the result of the query. If no rows have changed then it means that the user exists and I can show the error. Either of these approaches would not violate the consistency of my data. But I am looking for the best practices on how to handle this kind of problem.
Your first instinct was correct. To protect against duplicates, define a UNIQUE constraint on that column. Then catch any exception resulting from a violation of that constraint.
SQL lacks an atomic insert-if-not-exists command. You will see code using a nested SELECT statement, but such code is not atomic, so you would still need to trap for the UNIQUE constraint violations.
This Question is basically a duplicate. Search StackOverflow for more discussion and examples.
By the way, I would recommend against using email address as a primary key. If a user wants to change their email address on their account, you will have to update all related records using that value as a Foreign Key. I suggest using a Surrogate Key instead of a Natural Key almost always.
The chance of that happening is so remote you really don't have to consider it. Especially if you use email validation before someone can use the system. If you still are worried you can minimize the chance by using a synchronize operation on the call that checks for the existence of the email. The only way this would not work is if you have a clustered environment with the code running on 2 or more load balanced servers.

Check duplicate value before insertion using Hibernate

I am using Spring+Hibernate for my application. I have a few CRUD operations. Before inserting, I need to check if a similar entry is already in the database, if yes it should not be inserted.
For eg: If I am trying to create a Department, before inserting the row, I should check if a department with the same name already exist or not. If yes, the method returns error message.
Now, I know the unique key constraint can be set on the column to do the check. But, I want to know if there is any other way to do this.
The only way I can think of is first fetching all the departments from the database and check against each object.
Please let me know if there is any other way.
The only way I can think of is first fetching all the departments from the database and check against each object.
You don't need to fetch all departments form the database. It should be enough to search the database for the department with the name you want to insert. Since the name should have a unique key anyways it should be fast enough.
If your #Id attribute is department name, then the saveOrUpdate API of Hibernate will check if an object with that id is already present in the DB. If so it will update, else it will create a new entry. Hope this should help you. See this link.
You can try find object from database by "get" method:
Cat cat = (Cat) sess.get(Cat.class, id);
If received object is null, you can add new.
Also for performance better use query with "count" predicate, for avoid whole object loading.

Hibernate + "ON DUPLICATE KEY" logic

I am looking for a way to save or update records, according to the table's unique key which is composed of several columns).
I want to achieve the same functionality used by INSERT ... ON DUPLICATE KEY UPDATE - meaning to blindly save a record, and have the DB/Hibernate insert a new one, or update the existing one if the unique key already exists.
I know I can use #SQLInsert( sql="INSERT INTO .. ON DUPLICATE KEY UPDATE"), but I was hoping not to write my own SQLs and let Hibernate do the job. (I am assuming it will do a better job - otherwise why use Hibernate?)
Hibernate may throw a ConstraintViolationException when you attempt to insert a row that breaks a constraint (including a unique constraint). If you don't get that exception, you may get some other general Hibernate exception - it depends on the version of Hibernate and the ability of Hibernate to map the MySQL exception to a Hibernate exception in the version and type of database you are using (I haven't tested it on everything).
You will only get the exception after calling flush(), so you should make sure this is also in your try-catch block.
I would be careful of implementing solutions where you check that the row exists first. If multiple sessions are updating the table concurrently you could get a race condition. Two processes read the row at nearly-the-same time to see if it exists; they both detect that it is not there, and then they both try to create a new row. One will fail depending on who wins the race.
A better solution is to attempt the insert first and if it fails, assume it was there already. However, once you have an exception you will have to roll back, so that will limit how you can use this approach.
This doesn't really sound like a clean approach to me. It would be better to first see if an entity with given key(s) exists. If so, update it and save it, if not create a new one.
EDIT
Or maybe consider if merge() is what you're looking for:
if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
the persistent instance is returned
the given instance does not become associated with the session, it remains detached
< http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html
You could use saveOrUpdate() from Session class.

Categories

Resources