My POJO is using JPA and when I apply unique value in the column is not working for me I tried to use the UniqueConstraint and also not working for me .
below is my code
#Entity
#Table(name = "users", uniqueConstraints={#UniqueConstraint(columnNames = {"user_id"}),#UniqueConstraint(columnNames = {"username"}),#UniqueConstraint(columnNames = {"email"})})
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="user_id",unique=true,nullable = false)
private int UserId;
#Column(name = "username" ,unique=true,nullable = false)
private String Username;
#Column(name = "email",unique=true ,nullable = false)
private String email;
#Column(name = "firstname",nullable = false)
private String firstname;
#Column(name = "lastname", nullable = false)
private String lastname;
#Column(name = "password", nullable = false)
private String password;
#Column(name = "active")
private int active;
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="user_role", joinColumns=#JoinColumn(name="user_id"), inverseJoinColumns=#JoinColumn(name="role_id"))
private Set<Role> roles;
below is the generated table in the database (MySQL)
| users | CREATE TABLE users (
user_id int(11) NOT NULL,
username varchar(255) NOT NULL,
active int(11) DEFAULT NULL,
email varchar(255) NOT NULL,
firstname varchar(255) NOT NULL,
lastname varchar(255) NOT NULL,
password varchar(255) NOT NULL,
PRIMARY KEY (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
Hibernate log after spring start
Hibernate: create table users (user_id integer not null, username varchar(255) not null, active integer, email varchar(255) not null, firstname varchar(255) not null, lastname varchar(255) not null, password varchar(255) not null, primary key (user_id)) engine=InnoDB
Hibernate: alter table users drop index UKfnranlqhubvw04boopn028e6
Hibernate: alter table users add constraint UKfnranlqhubvw04boopn028e6 unique (username, email)
Hibernate: alter table users drop index UK_r43af9ap4edm43mmtq01oddj6
Hibernate: alter table users add constraint UK_r43af9ap4edm43mmtq01oddj6 unique (username)
Hibernate: alter table users drop index UK_6dotkott2kjsp8vw4d0m25fb7
Try like this:
#Entity
#Table(name="users",uniqueConstraints=#UniqueConstraint(columnNames={"user_id","username","email"}))
public class Users {
Apparently there's nothing wrong with this code. unique=true in #Column is a shortcut for #UniqueConstraint(columnNames = {"user_id"} and other particular constraints. You could only use one of them except for multiple unique constraints.
But if you are confused why the generated CREATE TABLE doesn't contain these unique constraints, check the log, you can find alter table commands just after CREATE TABLE.
In this case commands could be,
alter table users add constraint UK_some_id unique (username)
alter table users add constraint UK_some_id unique (email)
Hope this help.
I had the same problem here, set length to your unique columns.. It worked here. Do
#Column(name = "userName", length = 50, unique = true)
if you set unique in #Column
that's mean let your JPA provider create the database for you - it will create the unique constraint on the specified column.
But after creating a database, or you alter it once created,
then unique doesn't have any effect
in jpa the id is already unique so to make username and email unique add the statement
unique=true
to the corresponding #Column annotation.
PS : remember the unique cannot be null when insert new item you should drop the table before run the application and remove uniqueConstraints in table annotation
Set the column to have the fixed length make it work because mysql size for unique constrains limited to 1000 bytes
#Column(name = "username", length = 200, unique = true)
Use #javax.persistence.Column(unique = true).
Dont forget to restart your application.
&& you cant alter your column if there are still duplicated values in it.
drop your table, and recreate it with your generated ddl. (if ure not usin springboot)
&& if youre using springboot, go to your application.properties & set spring.jpa.hibernate.ddl-auto to update
This updates the schema if necessary.
The column needs to be non nullable for it to be unique!
#Column(unique = true) will NOT work
#Column(unique = true, nullable = false) will work
If the database or schema already exists before adding the uniqueConstraints then it won't work.
So drop the database or schema and run the application to create new database with these uniqueConstraints
DROP DATABASE database_name;
Related
I'm using this hibernate-types that allows hibernate to translate SQL layer data types into java classes in my springboot application, here I'm trying to add a text array field called user array.
#Entity
#Table(name = "user_update")
#Getter
#Setter
#NoArgsConstructor
#RequiredArgsConstructor
#TypeDef(name = "list-array", typeClass = ListArrayType.class)
public class UserUpdate {
#Id #NonNull private String userKey;
#Column #NonNull private String userName;
#Column #NonNull private Instant updatedAt;
#Type(type = "list-array")
#Column(columnDefinition = "text[]")
#NonNull
private List<String> userArray;
}
I can insert data into the table, but now I want to add a test and I see the following error message from the table.sql
CREATE TABLE IF NOT EXISTS user_update (
user_key VARCHAR(255) NOT NULL,
user_name VARCHAR(255) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
user_array TEXT ARRAY NOT NULL,
PRIMARY KEY(org_key)
);
maybe it is because the test I'm running uses #DataJpaTest and for some reason it can not recognize the new text[] field ?
Error executing DDL "create table user_update (user_key varchar(255) not null, user_name varchar(255), user_array text[], updated_at timestamp, primary key (user_key))" via JDBC Statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "create table user_update (user_key varchar(255) not null, user_name varchar(255), user_array text[*][], updated_at timestamp, primary key (user_key))"; expected "(, ARRAY, INVISIBLE, VISIBLE, NOT, NULL, AS, DEFAULT, GENERATED, ON, NOT, NULL, DEFAULT, NULL_TO_DEFAULT, SEQUENCE, SELECTIVITY, COMMENT, CONSTRAINT, COMMENT, PRIMARY, UNIQUE, NOT, NULL, CHECK, REFERENCES, ,, )"; SQL statement:
With #DataJpaTest Spring will instruct Hibernate to create the schema and that will use the information that you provided in your annotations, but it seems this is not legal for H2.
Try using the following instead:
#Column(columnDefinition = "text array")
Does anybody knows how to set the constraint name for primary key (PK_[name]) ,check (CK_[Name]),Default [DF_[Name]], Foreign Key (Fk_[Name]) ,Unique ..
by using Annotations or xml config for example i want that Table ::::
CREATE TABLE ACCOUNT (
[ID] INT NOT NULL IDENTITY(1,1),
[USERNAME] VARCHAR(50) NOT NULL,
[PASSWORD] VARCHAR(50) NOT NULL,
[EMAIL] VARCHAR(100) NOT NULL,
[GENDER] INT NOT NULL ,
[ADDRESS] INT,
[AGE] INT CONSTRAINT DF_tblAccount_Age DEFAULT 0,
CONSTRAINT PK_tblAccount_ID PRIMARY KEY([ID]),
CONSTRAINT UQ_tblAccount_Address UNIQUE(ADDRESS),
CONSTRAINT FK_tblAccount_Gender FOREIGN KEY([GENDER]) REFERENCES GENDER([ID]),
CONSTRAINT FK_tblAccount_Address FOREIGN KEY([ADDRESS]) REFERENCES ADDRESS([ID]) ON DELETE SET NULL,
CONSTRAINT CK_tblAccount_Age CHECK ([AGE] > 0 AND [AGE] <100)
)
Translate it into annotation class or [name].hbm.xml ,
does Hibernate support to use constraint name or i must alter the tables
every time i create a new class ...
I searched and i find 0 results about constraint names !!
Annotation Class Example :::
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="ID")
// -->>Add Primary Key constraint Name Here !! ???
private int id;
#Column(name="Name")
private String name;
#Column(name="Surname")
private String surname;
#Column(name="age")
// -->>Add Check constraint Name Here !! ???
private String age;
#OneToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY)
#OnDelete(action=OnDeleteAction.CASCADE)
#JoinColumn(name="Address" , referencedColumnName="id",nullable=false)
// -->>Add Foreign Key constraint Name Here !! ???
private Address address;
In JPA, you can do this at class level, using #Table annotation properties, where you specify constraints names. For primary key id mapped to column id:
#Table(uniqueConstraints = #UniqueConstraint(columnNames = "ID", name = "PERSONS_PK_CONSTRAINT"))
Im getting this error from hibernate when trying to do a criteria search
ERROR org.hibernate.property.access.spi.GetterMethodImpl - HHH000122:
IllegalArgumentException in class: packagename.domain.User, getter method of
property: id
For this criteria search
#Override
public List<Story> findStoryByAuthor(Long userId) throws Exception {
Criteria criteria = currentSession().createCriteria(Story.class);
criteria.add(Restrictions.eq("author", userId));
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
List<?> stories = criteria.list();
return (List<Story>) stories;
}
We are finding stories via the user that created it so here are the property definitions. Trying not to clutter this so if you guys want to see more code let me know.
Story has a Many to One relationship with User
#ManyToOne(fetch = FetchType.LAZY, targetEntity = User.class)
#JoinColumn(name = "author_user_id", referencedColumnName = "id")
public User getAuthor() {
return author;
}
Users have no reference to story but its id property is correctly annotated
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
And lastly the database structure
Stories Table
id bigint NOT NULL DEFAULT nextval('stories_seq'::regclass),
parent_id bigint,
author_user_id bigint NOT NULL,
title character varying(100) NOT NULL,
dt_created timestamp without time zone NOT NULL,
dt_last_updated timestamp without time zone NOT NULL DEFAULT now_utc(),
thumbs_up bigint DEFAULT 0,
thumbs_down bigint DEFAULT 0,
CONSTRAINT pk_stories PRIMARY KEY (id),
CONSTRAINT fk_stories_author_user_id_users FOREIGN KEY (author_user_id)
REFERENCES public.users (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
Users Table
id bigint NOT NULL DEFAULT nextval('users_seq'::regclass),
first_name character varying(255),
last_name character varying(255),
email character varying(255) NOT NULL,
user_name character varying(255),
password character varying(255),
phone character varying(255),
address character varying(500),
city character varying(255),
state character varying(255),
zip integer,
preferred_language character varying(255),
note character varying(32000),
active boolean DEFAULT true,
active_paid boolean DEFAULT false,
CONSTRAINT pk_user_id PRIMARY KEY (id),
CONSTRAINT users_unique_fields UNIQUE (email, user_name)
FYI
all basic dao functions (add, update and delete) work (full unit test coverage). I have another criteria search, almost identical but searches on the email field and works fine. so this error is something with the user reference
Please try with
criteria.add(Restrictions.eq("author.id", userId));
author property is of class User so you need to reference its id property for the equality.
I want to persist a objects by using JPA in a MYSQL-database. Here ist my create script:
CREATE TABLE toolboxAccount (
idtoolboxAccount INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
username VARCHAR(30) NOT NULL ,
password_2 VARCHAR(30) NOT NULL ,
PRIMARY KEY(idtoolboxAccount));
CREATE TABLE config (
idconfig INT NOT NULL AUTO_INCREMENT,
toolboxAccount_idtoolboxAccount INTEGER UNSIGNED NOT NULL ,
defaultExportPath VARCHAR(255) NULL ,
PRIMARY KEY(idconfig) ,
INDEX config_FKIndex1(toolboxAccount_idtoolboxAccount),
FOREIGN KEY(toolboxAccount_idtoolboxAccount)
REFERENCES toolboxAccount(idtoolboxAccount)
ON DELETE CASCADE
ON UPDATE CASCADE);
CREATE TABLE connection (
idconnection INT NOT NULL AUTO_INCREMENT,
toolboxAccount_idtoolboxAccount INTEGER UNSIGNED NOT NULL ,
url VARCHAR(255) NULL ,
username VARCHAR(30) NULL ,
password_2 VARCHAR(30) NULL ,
site VARCHAR(30) NULL ,
PRIMARY KEY(idconnection) ,
INDEX connection_FKIndex1(toolboxAccount_idtoolboxAccount),
FOREIGN KEY(toolboxAccount_idtoolboxAccount)
REFERENCES toolboxAccount(idtoolboxAccount)
ON DELETE CASCADE
ON UPDATE CASCADE);
CREATE TABLE export (
idexport INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
connection_idconnection INT NOT NULL ,
nameOfExportZIP VARCHAR(255) NOT NULL ,
PRIMARY KEY(idexport) ,
INDEX export_FKIndex1(connection_idconnection),
FOREIGN KEY(connection_idconnection)
REFERENCES connection(idconnection)
ON DELETE CASCADE
ON UPDATE CASCADE);
The classes are
ToolboxaccountEntity
#Entity
#Table(name = "toolboxaccount", schema = "", catalog = "toolboxtest")
public class ToolboxaccountEntity {
#Id
#GeneratedValue(generator="my_seq")
#SequenceGenerator(name="my_seq",sequenceName="MY_SEQ", allocationSize=1)
private long idtoolboxAccount;
private String username;
private String password_2;
#OneToOne(cascade = CascadeType.PERSIST)
private ConfigEntity configEntity;
#OneToMany(cascade = CascadeType.PERSIST)
private List<ConnectionEntity> connections;
public List<ConnectionEntity> getConnections() {
return connections;
}
public void setConnections(List<ConnectionEntity> connections) {
this.connections = connections;
}
...
ConnectionEnity
#Entity
#Table(name = "connection", schema = "", catalog = "toolboxtest")
public class ConnectionEntity {
#Id
#GeneratedValue(generator="my_seq")
#SequenceGenerator(name="my_seq",sequenceName="MY_SEQ", allocationSize=1)
private long idconnection;
private String url;
private String username;
private String password_2;
private String site;
#Column(name = "idconnection")
public long getIdconnection() {
return idconnection;
}
public void setIdconnection(int idconnection) {
this.idconnection = idconnection;
}
...
The persisting of ToolboxAccountEntity works but when I add a ConnectionEntity I get following error:
Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`toolboxtest`.`connection`, CONSTRAINT `connection_ibfk_1` FOREIGN KEY (`toolboxAccount_idtoolboxAccount`) REFERENCES `toolboxaccount` (`idtoolboxAccount`) ON DELETE CASCADE ON UPDATE CASCADE)
Error Code: 1452
Call: INSERT INTO toolboxtest.connection (PASSWORD_2, SITE, URL, USERNAME) VALUES (?, ?, ?, ?)
bind => [4 parameters bound]
2 things:
1) If you want to make a insert operation, make sure that the record doesnt exists in the Database.
2) If you want to make an update operation, make sure that the record exist in the database.
3) Remember that the records has to be well relationships, primary key, foreign key.
That kind of error, is very common when a record already exists.
Regards! Tell us if you correct your issue
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I was faced with the below problem
problem
P.S. Have a look at the comments :) on the above link
And while solving it, I now have a question about how the unique constraint is implemented in hibernate, I have started to believe that it fires a select query (I am not sure about this), and then "some how" performs the validation.
I am not very convinced with the explanation
Hibernate creates a "unique" index on that column, and it's the database that then enforces the uniquness.
For example, if you have a class:
#Entity
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserEmailAddressEntity {
#Id
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Basic(optional = false)
private boolean primaryEmail;
#ManyToOne(optional = false)
private UserEntity user;
#NaturalId // this means the email column must be unique
#Basic(optional = false)
private String email;
#Basic(optional = false)
private String token;
#Basic(optional = false)
private boolean verified;
}
Hibernate creates a table like so: (for PostgreSQL, but the idea is the same for pretty much all RDBMS)
CREATE TABLE useremailaddressentity
(
id bigint NOT NULL,
email character varying(255) NOT NULL,
primaryemail boolean NOT NULL,
token character varying(255) NOT NULL,
verified boolean NOT NULL,
user_id bigint NOT NULL,
CONSTRAINT useremailaddressentity_pkey PRIMARY KEY (id),
CONSTRAINT fk279a5e06c843ec30 FOREIGN KEY (user_id)
REFERENCES userentity (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
-- note the `UNIQUE` here:
CONSTRAINT useremailaddressentity_email_key UNIQUE (email)
)
I tried to replicate this behavior , I using using grails 1.3.7 and found it to be reproducible
class Child {
String name
static constraints = { name(unique:true) }
}
table created
CREATE TABLE `child` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
)
Queries fired on
child.save()
Hibernate: select this_.id as id0_0_, this_.version as version0_0_, this_.created_by as created3_0_0_, this_.date_created as date4_0_0_, this_.last_updated as last5_0_0_, this_.name as name0_0_, this_.updated_by as updated7_0_0_ from child this_ where this_.name=?
Hibernate: insert into child (version, created_by, date_created, last_updated, name, updated_by) values (?, ?, ?, ?, ?, ?)
The reason i think i hibernate fires the above query is to check the unique constraint, And in case you are trying to perform an update then this query will result in having another object with the same identifier in memory, which could the lead to nonuniqueobjectexception.
I thinking this is hibernate and not grails, have not double checked this in java/hibernate.
Thanks