@Column(unique=true) does not seem to work
Asked Answered
D

11

38

Even though I set the attribute to be @Column(unique=true), I still insert a duplicate entry.

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(unique=true )
    private String name;

    ...
}

I set the name using regular EL in JSF. I did not create table using JPA

Dorton answered 16/8, 2010 at 18:18 Comment(2)
It would be neat if your JPA vendor (ie hibernate) took care of updating the schema in this scenario, but unfortunately it doesn't. I wonder if there is a bug/feature request for itDybbuk
hibernate annotation: @Column(unique=true) String userName; Below is my hibernate denerated DDL : CREATE TABLE user ( id bigint(20) NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, password varchar(255) NOT NULL, userName varchar(255) NOT NULL, PRIMARY KEY (id), UNIQUE KEY userName (userName) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin still I am able to insert duplicateHammerfest
M
12

I did not create table using JPA

Then you should add the unique constraint to your table in your CREATE statement, for example, if you are using MySQL:

create Customer (id int primary key, name varchar(255) unique);
Millionaire answered 16/8, 2010 at 23:34 Comment(1)
It worked for me Thanks! I also turned off auto table creation from JPA and @Column(unique=true ) didn't work.Edythedythe
D
30

The unique=true element of the Column annotation and / or the UniqueConstraint annotation that can be used at the table level are used to specify that a unique constraint is to be included in the generated DDL.

In other words, they don't do anything during the runtime, the verification is left to the database (which makes sense as unicity can't be tested at the Java level reliably1) and if for whatever reason you don't have the corresponding constraint(s) defined at the database level, nothing will happen.

Add the constraint manually:

ALTER TABLE Customer ADD CONSTRAINT customer_name_unq UNIQUE (name);

See also

1 Unless you acquire a table lock (ouch!), you can't check for unicity with a SQL query in a concurrent environment.

Dilapidation answered 17/8, 2010 at 0:32 Comment(1)
You say that "Unless you acquire a table lock (ouch!), you can't check for unicity with a SQL query in a concurrent environment." But even a pragmatic check (if there already is a row with this attribute value) without a lock is helpful. It would be correct in, say, 99 % of all cases. In any case, a (quick and dirty) uniqueness check from the Java bean class is very much needed.Isodimorphism
D
23

For future users stumbling on this issue. There are lots of great suggestions here; read through them as well as your error messages; they will be enough to resolve your problem.

A few things I picked up in my quest to get @Column(unique=true) working. In my case I had several issues (I was using Spring Boot, FYI). To name a couple:

  • My application.properties was using spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect despite using MySQL 8. I fixed this with spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect. Check your version (I did this through the command line: mysql> STATUS).
  • I had a User class annotated as an @entity which meant that JPA was trying to create a user table which is one of MySQL's (as well as postgres) reserved keywords. I fixed this with @Table(name = "users").
Durative answered 2/3, 2019 at 19:20 Comment(4)
Big thumbs up for this comment. Stumbled upon this very issue as wel.Sardis
for those scratching head on mysql 8 for this issue, using this answer solved it. spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8DialectTungsten
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect generate with InnoDB engineBoiling
For me it worked using org.hibernate.dialect.MySQL57Dialect instead of org.hibernate.dialect.MySQL5Dialect to apply the unique constraint! The length as mentioned in other posts was not required!Chalk
M
12

I did not create table using JPA

Then you should add the unique constraint to your table in your CREATE statement, for example, if you are using MySQL:

create Customer (id int primary key, name varchar(255) unique);
Millionaire answered 16/8, 2010 at 23:34 Comment(1)
It worked for me Thanks! I also turned off auto table creation from JPA and @Column(unique=true ) didn't work.Edythedythe
S
11

For InnoDB tables , there are limit for indexed columns. That means, you have to set max length for te field:

@Column(unique = true, length = 32)
private String name;
Stewart answered 21/4, 2018 at 15:32 Comment(2)
@Column(..., length = ...) generates with MyISAM engine.Boiling
BINGO! the default size of varchar that was auto-generated was too long. adding a limit solved the issue. THANKS!Libb
H
9

Try specifying the unique constraint at the class level using

@Table(uniqueConstraints={@UniqueConstraint(columnNames={"name"})})
public class Customer {
...
    private String name;
}

@Column(unique=true) doesn't work for me but when I used @UniqueConstraint at the class level, the column in the database (MySql) was appropriately set as unique.

I hope this helps someone else who may face this same issue in the future

Hardan answered 16/7, 2017 at 18:22 Comment(7)
I thought as much @Kukeltje but it doesn't work for me. I use springboot with hibernate as JPA provider and MySql dbms. However, as I pointed out, '@UniqueContraint' within '@Table' on the class level works perfectly for me.Hardan
"Doesn't work" is a little vague... Does it not generate the unique constraints on the fields? Or are they not enforced? Or... And what hibernate version do you use? And what Database? Please be as specific as possible,Martelli
Thanks for your comments @Kukeltje. I have conducted tests on the two cases and found out that @Column(unique=true) actually works(unique constraint enforced) but only if the table does not already exist in the database. Using @Column(unique=true) afterwards (i.e when the table had been generated previously) does not update the table with the unique constraint. However @UniqueConstraint works for me all the time whether the table already exists or not. Hibernate version is 5.0.12, My database is MySQLHardan
@Martelli , it did not have created the unique index for me as well. This is my annotation @Column(columnDefinition = "varchar(100) not null", unique = true). But, if I remove the columnDefinition part, it works perfectly fine.Grooved
Update to the above comment : To solve the issue, I have moved the unique inside column definition and it worked. Looks like the column definition is dominating the unique property.Grooved
@Hardan I tried your comments on spring boot 1.4.1. unique is only honoured when it is already defined in database. Table is not getting updated by providing unique=true... @Column(name="email", nullable=false, unique=true, length=30) this dont make any effect until I changed email colum property manually in db.Confirmatory
@Hardan I tried your comments on spring boot 1.4.1. unique is only honoured when it is already defined in database. Table is not getting updated by providing unique=true... @Column(name="email", nullable=false, unique=true, length=30) this dont make any effect until I changed email colum property manually in db.Confirmatory
P
6

I was also facing the similar issue but got it resolved.

  • First, drop the table from Database

      drop table Customer;
    
  • Stop your spring boot application and launch it again.

    This worked for me.

Ploughman answered 5/9, 2020 at 13:17 Comment(2)
Thanks, you saved my life.Catling
This works for me. There is nothing wrong with the constrain definition it is the table creation has to be refreshed by drop and created by doing operations of this answer.Misery
A
1

If table already existing on database and table existing non unique records, jpa dont set unique constraint to column. For solution:

  1. clean duplicated records or delete all records.
  2. then try to set unique constraint.
Apatetic answered 24/4, 2023 at 11:1 Comment(0)
C
0

Make sure to delete the tables created by hibernate in your database. And then re-run your hibernate application again.

Churrigueresque answered 26/9, 2018 at 7:16 Comment(1)
(This post does not seem to provide a quality answer to the question. Please either edit your answer and improve it, or just post it as a comment to the question.)Charliecharline
E
0

MySQL Hibernate Object Relational Mapping - Alter Contains after schema was generated.

  1. In case you change your entity class [Customer] after the Hibernate generated the schemas, you can drop the schema and re-generate it. The constrains will apply.

  2. Instead of dropping schemas you can manually alter the table

ALTER TABLE Customer ADD CONSTRAINT customer_name_unq UNIQUE (name);

Extracurricular answered 30/9, 2020 at 11:40 Comment(0)
T
0

It also happens when you have added the validation in the middle of the running application where all the databases and tables were already created.

As @Column is the persistence level annotation, it only works when the unique constraint is found in the required fields.

So just add all required annotations, delete all tables and then re-run the application. In this way the application will again create all the tables marked with @Entity annotation and also add 'unique' constraint with it.

It is important to note that all @Column annotations will have the same behaviour hence it is advised to add all required persistence level validations before head so that you don't need to delete tables again and again.

Threadgill answered 25/3, 2023 at 11:11 Comment(0)
W
0

Generally it happens, when you have already populated the table and later added the unique column options.

e.g  @Column(nullable = false, unique = true)
    private String title;

If you are using Spring JPA for populating the table structure, then you might need to drop the table and let it populate again.

Please make sure to mention this is application.properties : spring.jpa.hibernate.ddl-auto=update

It will work.

Wiring answered 19/5, 2024 at 13:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.