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.
Related
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.
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 have an entity:
#Entity
public class MyEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = Columns.ID)
private Long id;
// getter & setter
}
Then, I create an instance of the entity MyEntity my = new MyEntity(); and want to save it with DAO (using Spring Data for JPA) - dao.save(my);. I got the following exception:
Caused by: Exception [EclipseLink-6023]
(Eclipse Persistence Services - 2.4.0.v20120608-r11652):
org.eclipse.persistence.exceptions.QueryException
Exception Description: The list of fields to insert into the table
[DatabaseTable(my_entity)] is empty.
You must define at least one mapping for this table.
Query: InsertObjectQuery(null)
When I add another, useless column to the entity with a default value
private int nothing = 6;
Exception disappears. Any solution for that?
This topic does not help me. I use EclipseLink + MySQL + Spring Data.
This is because you have no fields, and are using a generated id, so there is nothing to insert. You either need to add another field, or need to use TABLE id generation instead of IDENTITY (I recommend never using IDENTITY as it does not support pre-allocation).
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!
I'm trying JPA with a very simple class for the Play! framework and I'm having some problems with the id column.
My sql database has only two columns:
CREATE TABLE IF NOT EXISTS `auto` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
)
And my model is:
#Entity
#Table(name = "auto")
public class Auto extends Model{
#Column(insertable = false, updatable = false)
public int id;
public String name;
public Auto(String name){
this.name = name;
}
}
Everything works fine without this part:
#Column(insertable = false, updatable = false)
public int id;
As soon as I add public int id; I'd get this error though: A JPA error occurred (Unable to build EntityManagerFactory): Repeated column in mapping for entity: models.Auto column: id (should be mapped with insert="false" update="false")
And that's the reason I've added the column annotation, but it doesn't work with that neither, now I'm getting:
A javax.persistence.PersistenceException has been caught, org.hibernate.PropertyAccessException: could not set a field value by reflection setter of models.Auto.id
I'm testing the model this way: new Auto("bmw").save(); save() is a method from the model class in the playframework.
Anyone know why I'm having this problem? Thanks!
Hmm, try it completely without the id field. Looks like Playframework auto-creates an Id field if extending the Model class. See here:
"...
If you have used JPA before, you know that every JPA entity must provide an #Id property. Here the Model superclass provides an automatically generated numeric ID, and in most cases this is good enough.
..."
class Model already adds an id field, of type Long. This is conflicting with the id field you add on your class definition.
Just remove the id field from Auto and it should work. I'm not sure if the definition of int(11) in your database is correct, but JPA should automatically solve that if required.
Should't the column be annotated similar to following ?
#Id
#GeneratedValue(generator="???_seq",strategy=GenerationType.SEQUENCE)
The problem you are having relates to underestimating what you are getting for ´free´ in the play framework.
Both the ID (your original question) and the getters and setters (your follow up comment) are generated automatically for you.
The id field comes from the Model class, which you are extending, and the getters and setters are automatically generated and used when you make a public field in your model, and then refer to it later as model.field.
While all models will have an Id provided for them, it is recommended to use your own custom IDs if they are to do anything more complex or meaningful.
If you need to add your own id field (for example, because it needs to be an Integer rather than a Long), you can extend GenericModel rather than Model.