How to stop a user from entering duplicate values - oracle

In one of my Java EE applications, I used a registration page to register new user and as soon as one registers, his/her registered values will be inserted into Oracle database. But there is no way of detecting duplicate values. So I thought about adding unique constraint to some column values. But later I learned, I can't declare more than one column as unique( In my case I already declared userid as primary key). But I need to make more than one column values unique (like emialid field). Again only adding unique can't help as if a user submits a form with duplicate value an exception will be caught and user won't be able to understand as he will be redirected to a blank page. So I have 2 questions.
1) How can I inform the user about inserting duplicate values?
and
2) How can I make more than one column unique in Oracle?
N.B. I don't know javascript!!

First, you certainly can declare multiple unique constraints on a table. You can declare that userid is a primary key and then declare emailid as unique. You can declare as many unique constraints as you'd like.
Second, your application would need to catch the duplicate key constraint and do something useful with it. Redirecting the user to a blank page would not be useful-- your application ought to catch the constraint exception and present a useful message to the user. For example, if you get an exception stating that the constraint UK_EMAILID was violated, you'd probably want to present an error message to the user saying something along the lines of "This email address already exists."

If you are using JPA, you can build a unique constraints :
#Entity
#Table(name = "entity_table_name", uniqueConstraints={
#UniqueConstraint(columnNames={"uniqueField1"}), // Unique value on one field.
#UniqueConstraint(columnNames={"uniqueField2", "uniqueField3"}) // Unique combination.
})
public class YourEntity {
private Long id;
private String uniqueField1;
private String uniqueField2;
private String uniqueField3;
private String uniqueField4;
// ...
}
The implementation (hibernate, eclipseLink) will take care of the oracle part.

Related

How does jpa annotation sequenceGenerator works and how to avoid duplicate entries?

#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqGen")
#SequenceGenerator(name = "seqGen", sequenceName = "seq", initialValue = 1)
private Long id;
Basically, i have three entities (fetched at the same times) that share the same sequenceName in my database.
I know for performance purpose, it's better to use the same tab for every entities with a SequenceGenerator.
When fetching a lot of datas, sometimes, i have a duplicate entries error, and basically changing the next_val of my sequence fix the problem temporarly.
I want to know how the SequenceGenerator work better and if there is a work around this issue ?
EDIT : could you explain me better what exactly is the purpose of a sequence and how his algorithm works ?
EDIT 2 : in a post, i saw this comment :
"Assume that you create a sequence object that has the CACHE option
enabled in Microsoft SQL Server 2012 or SQL Server 2014. When the
instance is under memory pressure, and multiple concurrent connections
request sequence values from the same sequence object, duplicate
sequence values may be generated. In addition, a unique or primary key
(PK) violation error occurs when the duplicate sequence value is
inserted into a table."
Is there a link with my current issue ?
There is no algorithm for sequence, it is +1 similar to autoincrement, also it has nothing to do with fetching your data that has duplicate entries.
Duplicate entries only mean that your database or code has a bad structure which leads to allowing data to be duplicated in the first place.
GenerationType. IDENTITY − In identity, the database is responsible to auto-generate the primary key. Insert a row without specifying a value for the ID and after inserting the row, ask the database for the last generated ID. Oracle 11g does not support an identity key generator. This feature is supported in Oracle 12c.
GenerationType. SEQUENCE − In sequence, we first ask the database for the next set of the sequence then we insert a row with return sequence id.
https://www.baeldung.com/hibernate-identifiers

How to create a serial numbers autogenerated in dynamoDb using annotations

I have created a pojo class in my java spring boot app and with respective annotations for doing create/update it's working fine but when i use the autogenerated key annotation it is creating some random id but i want those id column as serial numbers. Below i have given the annotations of my pojo class
#DynamoDBHashKey(attributeName = "id")
#DynamoDBAutoGeneratedKey
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
Generated random Id example
5d2af735-62ce-47d4-85bf-8beece056eb
How to generate the autogenerated column with serial numbers like we do in SQL autoincrement identity column?
No you cannot use DynamoDBAutoGeneratedKey to generate a incremented sequence,it is used to generate a random UUID.
The key generated in your case "5d2af735-62ce-47d4-85bf-8beece056eb" is standard UUID format which will help to scale and spread the data across the key space.
https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html
If you want to generate a incremental sequence what you can do is create a SQL table "sequence_table", which will have only 1 column as "sequence_id" which is set to auto increment.
Whenever you want to insert data to Dynamo you can first insert in the SQL sequence table and get the latest id.Using this id you can create a new Dynamodb entry. If the annotation DynamoDBAutoGeneratedKey is not used , you can use your own custom key value.Whenever multiple process try to add a new sequence to the sequence_table, each process will first take a lock on the table and then it will insert a new id. So this solution will work in case of distributed system as well.
However on a side note if your business logic does not care about the sequence of id, you should go with UUID only as it is highly scalable , as it is not recommended to have an integer which increments by 1 to generate a hash key of the table. In order for the table to scale according to the provisioned capacity, requests should spread evenly across the shards.
As keys adjacent in a sequence will be stored in the same partition space.
Also as one might expect new users to be more active than very old users, and so we would be gearing load towards whichever partition serves the newest user rows.

IBM DB2 + Doctrine - Auto increment in composite primary keys

My problem is easy to understand and many mentioned here in Stackoverflow with references to Doctrine docs.
Every entity with a composite key cannot use an id generator other
than "ASSIGNED". That means the ID fields have to have their values
assigned before you call EntityManager#persist($entity).
I tried this, getting last generated ID, adding + 1 to its value and persisting entity. The problem is that a third party software that uses the same IBM DB2 database, cannot add a row, because the auto increment index is not updated when I insert a row in that way.
Is there a way to make this work or a way to update the table auto increment index?
Thanks in advance.
EDIT
In order to help you to better understand what I want/have to achieve, I will show you my example.
EntityClass
class Entity
{
/**
* #ORM\Id
* #ORM\Column(type="string", name="serie")
*/
protected $serie;
/**
* #ORM\Id
* #ORM\Column(type="integer", name="reference")
* #ORM\GeneratedValue
*/
protected $reference;
// More code...
}
Multiple primary keys are allowed by doctrine, but for some reason, when I fill the entity this way
$entity = new Entity();
$entity->set("serie", date('Y')); // Custom setter that search the property and sets the value. In this case, current year as string
// More assignements, except for the autoincrement value
$em->persist($entity);
$em->flush();
It throws an exception saying that one of the ids is not filled and MUST be filled in a composite key entity, but it is an auto increment column and I need to make it work that way, find a way to get the next auto increment value for the table or update auto increment value for the table in IBM DB2. If not, the other third party software will crash if I get the max value of the auto increment column, increase that value by one and assign it to the entity manually.
The query:
SELECT presence FROM DB2ADMIN.PRESENCES WHERE serie LIKE 2017 ORDER BY presence DESC FETCH FIRST 1 ROWS ONLY;
If you need any further information, let me know.
There's two ways to do this, but since you don't have access to transactions (and apparently don't care about gaps), I don't recommend one of them.
The first way, which I'm recommending you not use, is to create a table to hold the generated value, incrementing that, and returning it. I previously answered a question about this for SQL Server, but the concept should translate. Note that some of the utility is lost since you can't generate the value in a trigger, but should still work. The primary remaining issue is that the table represents a bottleneck, which you're not getting much benefit out of.
The second way is just to use a separate SEQUENCE for each year. This is somewhat problematic in that you'd need to create the object each year, but would be much faster to get a number. You'd also be essentially guaranteed to have gaps.
Note that I'm always a little suspicious of primary keys where the value is incremented and has value, especially if gaps are allowed.

Understanding why relationship works

I am trying to understand why something works. I have a user model and within it I state that a User can have one Project e.g.
public function project()
{
return $this->hasOne('App\Project', 'userId');
}
Then within my Project model I define a user belongs to a Project
public function user()
{
return $this->belongsTo('App\User', 'userId');
}
So the way I understand this, a User should be allowed only one project? So within my Projects controller, I have my store function. I wont go over all of it but I essentially do the following
$newProject = new Project();
$newProject->projectName = Input::get('projectName');
$newProject->projectValue = Input::get('projectValue');
$newProject->userId = Input::get('user');
$newProject->save();
Now where I get the input user, this is always the logged in users id. So say I log into the system and I create a new project. This project then has my userID. This works fine.
My question is why does it allow me to create a second project with my same ID? So if I am logged into the system, I can essentially create as many projects as I want under my name. Does this not go against what my relatiohsips are defined as? According to the relationship, I should only be allowed to create one Project.
I am really just looking for information as to why this is allowed?
Thanks
In One to One,
You're linking a record to another record in another table.
That means, You're checking for single record rather than entire table.
So in your example, As you defined it's a correct One - to - One relationship.
Why it's adding new more than one project?
As i said before, We are checking for a single record.
How do i restrict that?
use UNIQUE constraint for Foreign key
User table
----------
`id` int,
`project_id` UNIQUE,
Project table
----------
`id` int,
`user_id` UNIQUE,
Example without Unique Constraint http://sqlfiddle.com/#!9/f2b07/1/0
(Try to put same values it will fail to insert)
Example with Unique Constraint http://sqlfiddle.com/#!9/dda24/1

Order by nullable property simultaneously with ordering by not nullable property in HQL

I have a table called Users in my database. Let's assume that User has only 3 properties
int ID;
string? Name;
string Login;
If user doesn't specify his name then Login is displayed. Otherwise Name is displayed. I wan't to get list of all users sorted by what is displayed. So if user specified Name, it is taken into consideration while sorting, otherwise his position on the list should be determined by Login. Eventually whole list should be ordered alphabetically. I hope I made myself clear...
Is that possible to do in HQL?
Just if someone have similar problem in future:
"order by coalesce(u.Name, u.Login) asc"

Resources