jpa - postgresql unique index annotation definition makes unique constraint instead - postgresql

I have the following annotation on the entity class. The database is postgresql. Unfortunately this creates the table with unique constraint, not unique index.
#Entity
#Immutable
#Table(
indexes = {
#Index(name = "MasterT75_unique_idx", columnList = "productdivision, giccode", unique = true)
}
)
public class MasterT75 extends ModelBaseValidate<MasterT75> {
...
}
i've found that, which describes well the difference of unique constraint and index.
https://www.postgresql.org/message-id/CAO8h7BJMX5V1TqzScTx2Nr1jH5iUFG8A071y-g1b_kdzpu9PDw%40mail.gmail.com
but i still don't understand, why hibernate doesn't create index as well (ok, not unique). because there is
uniqueConstraints = {}
parameter of #Table annnotation. so, if i want to make only unique constraint, i could use the latter one, but if i need index due to performance, i want to have index.

Related

How to create an "unique" contraint in MongoDB through Hibernate OGM and JPA

I'm trying to define a unique constraint on a non-id field. The answer might seem obvious:
#Entity
#Table(uniqueConstraints=#UniqueConstraint(columnNames={"col1"}))
public class MyEntity { ... }
However, this is not working. I've checked the indexes in the collection through the mongo command line, but there is no trace of a unique index (only a _id_ index is being generated).
I have also tried with the #Index annotation without joy:
#Entity
#Table(indexes={ #Index(name = "myIndex", columnList="col1", unique = true) })
public class MyEntity { ... }
The #Column(unique = true) annotation doesn't have any effect either.
How can I get Hibernate OGM to create a unique index for this collection?
Thank you in advance,
Guillermo
Hibernate OGM does not yet consider this index/constraint meta-data for MongoDB. I've opened OGM-910 for tracking it.

How to add a case insensitive JPA unique constraint?

I want to add a case insensitive unique constraint to a JPA entity.
Assume we have an entity employee which needs to have unique constraint for two columns NAME and PROJECT_TITLE where NAME is case insensitive.
Insertion of JoHn, PROJECT1 should cause unique constraint violation when a row JOHN,PROJECT1 already exists in database as JOHN, JoHn are same in our case.
The SQL for the above requirement is given below
ALTER TABLE employee ADD CONSTRAINT employee_name_unique
UNIQUE(LOWER(NAME),PROJECT_TITLE);
JPA doesn't support this kind of constraints. For a pure JPA solution, you'll have to use additional column. See the answer here: Case-insensitive JPA unique constraint?
#Entity Foo {
private value;
#Column(unique = true)
private valueLowercased;
#PrePersist #PreUpdate private prepare(){
this.valueLowercased = value == null ? null : value.toLowerCase();
}
}

dead-lock scenario in grails when trying to do ORM

I am writing a simple grails (2.3.1) sample application which uses postgresql(9.1)
I have two domain classes 'Nose' and 'Face'.
//Nose class
package human
class Nose {
static belongsTo=[face:Face]
static constraints = {
face nullable: true
}
}
//Face class
package human
class Face {
static hasOne = [nose:Nose];
static constraints = {
nose nullable: true
}
}
My database is empty and I am using static scaffold.
Now, grails does not allow me to insert into either, because one has foreign key constraint with other.
Also, when i try to insert directly in the postgresql database, i get the same foreign key constraint error:
human=# insert into nose (id, version, face_id) values (1, 0, 1);
ERROR: insert or update on table "nose" violates foreign key constraint "fk33afd3c47bf8db"
DETAIL: Key (face_id)=(1) is not present in table "face".
OR
human=# insert into face (id, version, nose_id) values (1, 0, 1);
ERROR: insert or update on table "face" violates foreign key constraint "fk2fd65d8476fd1b"
DETAIL: Key (nose_id)=(1) is not present in table "nose".
human=#
How to resolve this dead-lock condition ?

EntityFramework - many-to-many reference in the DB without a backreference in the model

In my application users can define Parameters, and then create SlideSets based on a grouping of parameters.
I am using code-first Entity Framework 5.0 and I have the following model:
class SlideSet {
public ICollection<Parameter> Parameter
}
class Parameter {}
A parameter might be used by many slidesets or none at all. However, in my domain a parameter has no need to reference a SlideSet, they are in separate bounded contexts (both SlideSet and Parameter are Aggregate Roots). As such, I don't want to put a reference from Parameter to SlideSet.
The table model (I don't care about table/column names) that I want is
Table SlideSet
Table Param
Table SlideSetParam
FK_SlideSet
FK_Param
I know I could model this by introducing a ParameterGroup entity or a Param.SlideSets collection, but it would exist solely for ORM mapping purposes (and cause serialization issues). Is there any other way to tell EF to generate this table model from my entities?
This should make you a Parameter w/o a navigation property:
modelBuilder.Entity<SlideSet>()
.HasMany(x => x.Parameters)
.WithRequired();
EDIT:
Based on the comment - that should be all together similar. This seems to work nicely what you're trying to do....
modelBuilder.Entity<SlideSet>()
.HasMany(x => x.Parameters)
.WithMany();
...and you can use it either way:
var slideset = new SlideSet { Parameters = new []
{
new Parameter{},
new Parameter{},
new Parameter{},
new Parameter{},
}
};
var slideset2 = new SlideSet { };
db.SlideSets.Add(slideset);
db.SaveChanges();
var slidesets = db.SlideSets.ToList();
var parameters = db.Parameters.ToList();
Console.WriteLine("");
db.SlideSets.Add(slideset2);
db.SaveChanges();
slidesets = db.SlideSets.ToList();
parameters = db.Parameters.ToList();
Console.WriteLine("");
...and the SQL:
CREATE TABLE [dbo].[Parameters] (
[ParameterID] [int] NOT NULL IDENTITY,
CONSTRAINT [PK_dbo.Parameters] PRIMARY KEY ([ParameterID])
)
CREATE TABLE [dbo].[SlideSets] (
[SlideSetID] [int] NOT NULL IDENTITY,
CONSTRAINT [PK_dbo.SlideSets] PRIMARY KEY ([SlideSetID])
)
CREATE TABLE [dbo].[SlideSetParameters] (
[SlideSet_SlideSetID] [int] NOT NULL,
[Parameter_ParameterID] [int] NOT NULL,
CONSTRAINT [PK_dbo.SlideSetParameters] PRIMARY KEY ([SlideSet_SlideSetID], [Parameter_ParameterID])
)
CREATE INDEX [IX_SlideSet_SlideSetID] ON [dbo].[SlideSetParameters]([SlideSet_SlideSetID])
CREATE INDEX [IX_Parameter_ParameterID] ON [dbo].[SlideSetParameters]([Parameter_ParameterID])
ALTER TABLE [dbo].[SlideSetParameters] ADD CONSTRAINT [FK_dbo.SlideSetParameters_dbo.SlideSets_SlideSet_SlideSetID] FOREIGN KEY ([SlideSet_SlideSetID]) REFERENCES [dbo].[SlideSets] ([SlideSetID]) ON DELETE CASCADE
ALTER TABLE [dbo].[SlideSetParameters] ADD CONSTRAINT [FK_dbo.SlideSetParameters_dbo.Parameters_Parameter_ParameterID] FOREIGN KEY ([Parameter_ParameterID]) REFERENCES [dbo].[Parameters] ([ParameterID]) ON DELETE CASCADE
...this makes the original tables practically 'agnostic' of the relationships (many-to-many) - while index table is automatically generated in the background.
You can also further customize that and make your own SlideSetParam (e.g. if you'd want to add additional fields there) with pretty much the same layout - just Parameters would have to point to that instead.

JPA Error : The entity has no primary key attribute defined

I am using JPA in my application. In one of the table, I have not used primary key (I know its a bad design).
Now the generated entity is as mentioned below :
#Entity
#Table(name="INTI_SCHEME_TOKEN")
public class IntiSchemeToken implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="CREATED_BY")
private String createdBy;
#Temporal( TemporalType.DATE)
#Column(name="CREATED_ON")
private Date createdOn;
#Column(name="SCH_ID")
private BigDecimal schId;
#Column(name="TOKEN_ID")
private BigDecimal tokenId;
public IntiSchemeToken() {
}
public String getCreatedBy() {
return this.createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getCreatedOn() {
return this.createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
public BigDecimal getSchId() {
return this.schId;
}
public void setSchId(BigDecimal schId) {
this.schId = schId;
}
public BigDecimal getTokenId() {
return this.tokenId;
}
public void setTokenId(BigDecimal tokenId) {
this.tokenId = tokenId;
}
}
Here In my project, eclipse IDE shows ERROR mark(RED colored cross) on this class and the error is "The entity has no primary key attribute defined".
Can anyone tell me, How to create an entity without primary key ?
Thanks.
You can't. An entity MUST have a unique, immutable ID. It doesn't have to be defined as a primary key in the database, but the field or set of fields must uniquely identify the row, and its value may not change.
So, if one field in your entity, or one set of fields in your entity, satisfies these criteria, make it (or them) the ID of the entity. For example, if there is no way that a user can create two instances in the same day, you could make [createdOn, createdBy] the ID of the entity.
Of course this is a bad solution, and you should really change your schema and add an autogenerated, single-column ID in the entity.
If your Primary Key(PK) is a managed super class which is inherited in an entity class then you will have to include the mapped super class name in the persistence.xml file.
Look at the bug report:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=361042
If you need to define a class without primary key, then you should mark that class as an Embeddable class. Otherwise you should give the primary key for all entities you are defining.
You can turn off (change) validation that was added.
Go to workspace preferences 'Java Persistence->JPA->Errors/Warnings' next 'Type' and change 'Entity has no primary key' to 'Warnning'.
In addition to http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#No_Primary_Key you can use some build-in columns like ROWID in Oracle:
Oracle legacy table without good PK: How to Hibernate?
but with care:
http://www.orafaq.com/wiki/ROWID
Entity frameworks doesn't work for all kind of data (like statistical data which was used for analysis not for querying).
Another solution without Hibernate
If
- you don't have PK on the table
- there is a logical combination of columns that could be PK (not necessary if you can use some kind of rowid)
-- but some of the columns are NULLable so you really can't create PK because of DB limitation
- and you can't modify the table structure (would break insert/select statements with no explicitly listed columns at legacy code)
then you can try the following trick
- create view at database with virtual column that has value of concatenated logical key columns ('A='||a||'B='||'C='c..) or rowid
- create your JPA entity class by this view
- mark the virtual column with #Id annotation
That's it. Update/delete data operations are also possible (not insert) but I wouldn't use them if the virtual key column is not made of rowid (to avoid full scan searches by the DB table)
P.S. The same idea is partly described at the linked question.
You need to create primary key ,If not found any eligible field then create auto increment Id.
CREATE TABLE fin_home_loan (
ID int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (ID));
Just add fake id field.
In Postgres:
#Id
#Column(name="ctid")
String id;
In Oracle:
#Id
#Column(name="ROWID")
String rowid;