org.hibernate.AnnotationException: Unable to create unique key constraint - java

I am using hibernate 4.3.5.Final version.
To handle reserve words at Database,I used a property in hibernate
hibernate.globally_quoted_identifiers = true.
And My pojo class having a unique column and it looks like
#Entity
#Table(name="theme1"
,catalog="theme2"
, uniqueConstraints = #UniqueConstraint(columnNames={"name1"})
public class Theme1 implements java.io.Serializable {
#Id #GeneratedValue(strategy=IDENTITY)
private Integer id;
#Column(name="name1", unique=true, nullable=false, length=32)
private String name1;
.....
Then when my SessionFactoryBean is loading it is failing with below error
Caused by: org.hibernate.AnnotationException: Unable to create unique key constraint (name1) on table theme1: database column 'name1' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
at org.hibernate.cfg.Configuration.buildUniqueKeyFromColumnNames(Configuration.java:1682)
at org.hibernate.cfg.Configuration.buildUniqueKeyFromColumnNames(Configuration.java:1614)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1450)
In the debugging process,I find issue is because of the property I add (hibernate.globally_quoted_identifiers).
When this property is added,Hibernate will append single quotes to handle reserved words.But while mapping from PhysicalToLogical,it is failed to map 'name1' with name1.Hence I got above error.
Can any one suggest how to handle above two cases(reserve words + UniqueConstraint) at a time.

When hibernate.globally_quoted_identifiers is set, Hibernate expects exact column name.
Check JPA with Hibernate 3.6.8.Final, PostgresSQL 9.1, SQLGrammarException - configuration issue? Weird SQL statement for more information.
So according to this, your column name and Table names in the pojo class need to be quoted.

Related

Hibernate + JPA does not find the column for an #ElementCollection table

I am trying to add an #ElementCollection but the column is not found after the setup, so I constantly receive an error. I use Spring + flyway for the set up. Everything happens in the public schema
So here is my big object:
#Entity
#Table(name = "my_big_table")
MyBigObject{
#Id
#Column(name=COL_ID)
#GeneratedValue(generator="gen_name")
#GenericGenerator(
name = "gen_name",
strategy = "seq_name"
)
#AttributeAccessor(CommonConstants.HIBERNATE_ACCESS_PROPERTY)
private long id;
...
...
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(
name = "my_small_table",
joinColumns = #JoinColumn(name = "big_object_id")
)
private List<MySmallObject> mySmallObjects;
}
Here is my embedded object:
#Embeddable
public class MySmallObject {
#Column(name = "small_object_type")
private String smallObjectType;
}
Then besides the existing my_big_table table I add my_small_table using flyway
create table if not exists my_small_table
(
big_object_id bigint not null,
small_object_type varchar(64) not null
);
alter table my_small_table
add constraint FK_my_small_table
foreign key (big_object_id)
references my_big_table (id);
After this the my_small_table is successfully created but any instance of MyBigObject cannot be found because it looks for a column in the my_small_table that does not exist. As you can see it does not understand that the column name should use an underscore.
Big error trace ands with the following message:
Caused by: org.postgresql.util.PSQLException: ERROR: column mysmalltab0_.smallobjecttype does
not exist
09:17:24.994 INFO - STDOUT: Hint: Perhaps you meant to reference the column "mysmalltab0_.smallobjecttype".
Do you know what I could forget? Could lombock annotations that I also use for both classes spoil the picture?
As it's stated in the documentation:
By default, the placement of the #Id annotation gives the default access strategy. When placed on a field, Hibernate will assume field-based access. When placed on the identifier getter, Hibernate will use property-based access.
But the usage of the #AttributeAccessor leads to the changing access strategy for the field that hold #Id and as result your #Column(name = "small_object_type") annotation just was ignored. You can try to put it on the appropriate getter and it should work. But it's considered a good practiсe not to mix up access strategies for the entity fields.

JPA Unique Renaming Unique Index

I'm creating an entity called Person, basically there is a column Integer sin, with the annotation #Column(name="per_sin", nullable=true, unique=true") The problem in the persistence xml file I ended up setting the hibernate to create, so it will create all the tables in the database. The problem is that it adds a constraint as UK_jkdfjalkfa, but I wanted to rename the constraint to UK_per_sin, but I tried putting it as an annotation as #UniqueConstraint(name="UK_per_sin"), but when it persists it still keeps on adding the constraint with random generated value.
For me, it's possible renaming the Unique Key constraint including an option into the #Table JPA tag:
#Table(name="tableName",
uniqueConstraints = #UniqueConstraint(name = "UK_per_sin", columnNames= { "per_sin" } ))
And also not including the unique option into the #Column tag:
#Column(name="per_sin", nullable=true)

JPA #UniqueConstraint doesn't see the columns

In Spring JPA I havean entity and I init the schema using FlywayDb.
My entity is:
#Entity
#Table(schema = "scheduler",
uniqueConstraints={#UniqueConstraint(name = "uq_task", columnNames = {"task", "date_at"})}
)
public class Task {
#Id
private Long id;
#Embedded
#Column(nullable = false)
private ITask task;
#Column(nullable = false)
private Date dateAt;
}
The schema is initialized as follows:
CREATE SCHEMA scheduler;
CREATE TABLE scheduler.task (
id bigserial primary key,
task bytea NOT NULL,
date_at timestamp NOT NULL
);
CREATE UNIQUE INDEX uq_task
ON scheduler.task(task, date_at);
Without the constraints on the entity, it works, with it doesn't. In particular I have the exception:
Caused by: org.hibernate.AnnotationException: Unable to create unique key constraint (task, date_at) on table task: database column 'task' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
at org.hibernate.cfg.Configuration.buildUniqueKeyFromColumnNames(Configuration.java:1684)
at org.hibernate.cfg.Configuration.buildUniqueKeyFromColumnNames(Configuration.java:1616)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1452)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
I use an H2 database.
ITask is an interface with several POJO implementations. ITask interface is annotated with #Embeddable.
My guess is that JPA tries to apply the unique constraints on columns that are not yet created by FlywayDb library. But this makes no sense to me.
Any idea?
After update of you question now I can guess that there is a problem with attribute in your ITask insterface please read that doc. In my opinion you have to override embbedable entity attribute to fix your problems.

ORA-00942: table or view does not exist - Hibernate with non-capital letters

I have the following error when I'm trying to map an entity:
ORA-00942: table or view does not exist
I figured out that the problem is that hibernate is trying to find the name of the table in "non-capital" (lowercase) letters, but Oracle has the tables names in capital letters (although the tables were created with non-capital letters).
I can fix the problem if I add the annotations #Table and #Column putting the names in capital letters, but I don't want to add those annotations.
I would like to know if there is any different way to do it.
Sql:
create table foo(
id integer not null
);
alter table foo
add constraint foo_pk
primary key (id);
Entity that is not working:
#Entity
public class Foo {
#Id
private Long id;
//getter and setter
}
Entity that is working:
#Entity
#Table(name = "FOO")
public class Foo {
#Id
private Long id;
//getter and setter
}
Thanks!
You can define a custom NamingStrategy, to make the specific table and column names translation from your entity to Database. Here is some example how to do it.
So, all you need is to create an implementation of NamingStrategy interface or extend some of existing strategies, modifying it's behaviour with the behaviour you want to get and then register this new strategy via hibernate XML configuration parameter hibernate.ejb.naming_strategy or via Configuration class.

JPA validation - OneToOne to same table

I just enabled the JPA validation in eclipse and in shows me some errors (The code is actually running fine).
I have an article entity and it holds a refrence to the next article and the previous entity (of the same type). The validator complains with the message:
Column "nextArticle" cannot be resolved on table "article"
What does this mean exactly? The SQL table has the columns as well. I tried also to map the variables to each other with the "mappedBy" and "JoinColumn" annotation, but was not able to resolve the validation error.
That's the class and validation error:
And that' the mapping:
Edit: Tried the suggestion from anttix: The columns in the table are named "nextArticle_id" and "prevArticle_id", so I came up with that code:
#OneToOne(mappedBy = "prevArticle")
#JoinColumn(name = "nextArticle_id")
public Article getNextArticle() {
return nextArticle;
}
#OneToOne(mappedBy = "nextArticle")
#JoinColumn(name = "prevArticle_id")
public Article getPrevArticle() {
return prevArticle;
}
But the validator complains now about the "mappedBy" annotation with the message:
In attribute 'prevArticle', the "mapped by" attribute 'nextArticle' has an invalid mapping type for this relationship.
Edit 2: I found the solution. I had to tell the validator the names of the columns in the actual database with the #Column annotation like this:
Eclipse can't find a column called prevArticle in the table. You should specifiy the column name for nextArticle and create a bidirectional relation with prevArticle to indicate that it does not need a foreign key column of its own.
#OneToOne
#JoinColumn(name = "next_id")
private Article nextArticle;
#OneToOne(mappedBy = "nextArticle")
private Article prevArticle;
You can omit the #JoinColumn from nextArticle if you want, but I would keep it there to make it clear which relation "owns" the foreign key column.
See also:
http://en.wikibooks.org/wiki/Java_Persistence/OneToOne

Categories