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.
Related
I am mapping some Java classes using hibernate on a database that I have no write access for. One of the fields used as a FK between ClientEpisodes and Physician's has 6 rows that contain a -1 for the FK. THis is obviously an invalid FK, but I need to still join and simply ignore these Physicians and have a null physician.
I am joining the class using
#JoinColumn(name = "epi_phid1", referencedColumnName = "ph_id", foreignKey = #ForeignKey(ConstraintMode.NO_CONSTRAINT))
private Physician physician;
I tried specifying NO_CONSTRAINT to see if it would ignore it then, but even still I get the following error:
javax.persistence.EntityNotFoundException: Unable to find private.package.info.Physician with id -1
Is there any way to tell Hibernate to ignore values that aren't valid such as the -1?
The #ForeignKey annotation with NO_CONSTRAINT value tells hibernate to not generate foreign keys, if schema generation is used. It doesn't have any effect on the internal entity validation in the JPA framework.
There is a hibernate specific #NotFound annotation which you could use:
#JoinColumn(name = "epi_phid1", referencedColumnName = "ph_id")
#NotFound(action = NotFoundAction.IGNORE)
private Physician physician;
However be advised that if you use this in a #OneToMany or #ManyToMany annotation which maps a Collection, hibernate will fill the invalid/missing entities with null (so the list will contain null value(s)).
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.
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.
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
I am using hibernate only with Annotations. My table looks something like this:
#Entity
#Table(name = "NetworkType",
uniqueConstraints = {#UniqueConstraint(columnNames = {"network_id", "type"})})
public class NetworkType implements Serializable {
#Id
private long id;
#Column(name = "network_id", nullable = false)
private long networkId;
#Column(name = "type", nullable = false)
private String type;
...
Currently when I write the same NetworkType twice, it throws an exception due to the UniqueConstraint (which is expected).
My thoughts are to just read the item first before checking. The problem is, my primary key is the Id, which I need because other tables references this table.
What's the best way to query for item for the "network_id" and "type" to verify the combination doesn't already exist?
I know I can do this with a Query manually, but is there a more Hibernate-y way of doing it?
In general, what's the proper way to "get" an object without using the PK? Are Criteria or Query the best way?
#UniqueConstraint is mainly used by database schema generation tools to create the data base schema. If used, they will generate the table with the columns mentioned in the #UniqueConstraint having unique constraint defined.
#UniqueConstraint doesn't have any impact/usage during data manipulation.
If you wish to achieve unique constraint behavior on network_id and type columns and your schema is already created, update your database schema to add the unique constraint on network_id and type columns. as below:
ALTER TABLE NetworkType
ADD CONSTRAINT uc_network_id_type UNIQUE (network_id, type)
Hope this helps!