dead-lock scenario in grails when trying to do ORM - postgresql

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 ?

Related

Entity Framework with MVVM problem. Violation of PRIMARY KEY constraint The duplicate key value is (2, 2)

I've been messing with this for 5 hours and I gave up.
I did basically identical relationship before and worked and now when I'm saving in my MVVM project, I get this error:
SqlException: Violation of PRIMARY KEY constraint 'PK_dbo.LecturerMeeting'. Cannot insert duplicate key in object 'dbo.LecturerMeeting'. The duplicate key value is (2, 2).
And also:
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.
I have 2 model classes, Meeting and Lecturer. In Lecturer class, I define in constructor:
public Lecturer()
{
Meetings = new Collection<Meeting>();
}
And also
public ICollection<Meeting> Meetings { get; set; }
Same in the Meeting class
public Meeting()
{
Students = new Collection<Student>();
Lecturers= new Collection<Lecturer>();
}
And:
public ICollection<Lecturer> Lecturers { get; set; }
But when I created a many-to-many relationship between meetings and student, EF created a table MeetingStudent.
Now it created LecturerMeeting, don't know if this changes anything
SQL code for LecturerMeeting relationship:
CREATE TABLE [dbo].[LecturerMeeting]
(
[Lecturer_Id] INT NOT NULL,
[Meeting_Id] INT NOT NULL,
CONSTRAINT [PK_dbo.LecturerMeeting] PRIMARY KEY CLUSTERED ([Lecturer_Id] ASC, [Meeting_Id] ASC),
CONSTRAINT [FK_dbo.LecturerMeeting_dbo.Lecturer_Lecturer_Id] FOREIGN KEY ([Lecturer_Id]) REFERENCES [dbo].[Lecturer] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.LecturerMeeting_dbo.Meeting_Meeting_Id] FOREIGN KEY ([Meeting_Id]) REFERENCES [dbo].[Meeting] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_Lecturer_Id]
ON [dbo].[LecturerMeeting]([Lecturer_Id] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_Meeting_Id]
ON [dbo].[LecturerMeeting]([Meeting_Id] ASC);
Please help.
I managed to find answer. Finally.
I didnt incluced another property when i get my Meeting from context.
I had
public async override Task<Meeting> GetByIdAsync(int id)
{
return await Context.Meetings.Include(m => m.Students).SingleAsync(m => m.Id == id);
Insted of:
public async override Task<Meeting> GetByIdAsync(int id)
{
return await Context.Meetings.Include(m => m.Students).Include(m => m.Lecturers)
.SingleAsync(m => m.Id == id);
}
Too stupid to find that faster.

jpa - postgresql unique index annotation definition makes unique constraint instead

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.

Adding column with foreign key into table.

I have some problem. I want to add new column into my table that references to other column in other table. I do something like that:
class m161202_153033_dodanie_informacji_o_obsludze_prawnej_do_pozyczki extends CDbMigration
{
public function safeUp()
{
$this->execute("ALTER TABLE loan ADD COLUMN administrator int NOT NULL DEFAULT 15 REFERENCES person (id) ON UPDATE CASCADE ON DELETE NO ACTION;");
}
public function safeDown()
{
$this->execute("ALTER TABLE loan DROP COLUMN administrator;");
}
}
But when i try to execute this migration i have this error:
Foreign key violation: 7
DETAIL: Key (administrator)=(15) doesn't appear in table "person"..
I know that there is no suck column "administrator" in my table. But i want to add new column "administrator" into loan table. I wanted to make "administrator" foreign key from person table, column "id". Can u help me, what am i doing wrong?
The error means that there is no row in person with id equal to 15, which would be required for the constraint to be fulfilled.
When you run that ALTER TABLE statement, the table has to be rewritten, and the new column is filled with the value 15.
Often it is easier to create a new column nullable and without default value (then ALTER TABLE will not rewrite the table) and use UPDATE to populate the new column. After that you can change the column definition to NOT NULL and add a default value.
Try this
class m161202_153033_dodanie_informacji_o_obsludze_prawnej_do_pozyczki extends CDbMigration
{
public function safeUp()
{
$this->execute("INSERT INTO person (id) VALUES (15) ON CONFLICT (id) DO NOTHING;");
$this->execute("ALTER TABLE loan ADD COLUMN administrator int NOT NULL DEFAULT 15 REFERENCES person (id) ON UPDATE CASCADE ON DELETE NO ACTION;");
}
public function safeDown()
{
$this->execute("ALTER TABLE loan DROP COLUMN administrator;");
}
}

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.

#UniqueConstraints not working on #JoinTable

I'm using Playframework 1.2.4 and PostgresSQL 9.1.2. I have the following entities: Recipe and RecipeItem. A Recipe has a set of RecipeItems. I've annotated the set of recipe items in the Recipe class as follows:
#Required
#MinSize(1)
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable( name = "RecipeItemForIngredients",
joinColumns = #JoinColumn(name = "recipeId"),
inverseJoinColumns = #JoinColumn(name = "recipeItemId"),
uniqueConstraints = #UniqueConstraint(name = "uq_recipeItemPerRecipe",
columnNames = {"recipeId", "recipeItemId"}))
public Set<RecipeItem> items = Sets.newHashSet();
But when I check the PgAdmin to see if the constraint has been applied to the RecipeItemForIngredients table I cannot find it. This is what PgAdmin shows.
CREATE TABLE recipeitemforingredients
(
recipeid bigint NOT NULL,
recipeitemid bigint NOT NULL,
CONSTRAINT recipeitemforingredients_pkey PRIMARY KEY (recipeid, recipeitemid),
CONSTRAINT fk5ac547a883708db FOREIGN KEY (recipeid)
REFERENCES recipe (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk5ac547ad6e1da8f FOREIGN KEY (recipeitemid)
REFERENCES "recipe$recipeitem" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT recipeitemforingredients_recipeitemid_key UNIQUE (recipeitemid)
)
Does anyone have an idea why this could be happening? Maybe this annotation is not supported by the ORM used by Playframework.
This constraint doesn't make much sense, and you have a stronger constraint by default anyway:
CONSTRAINT recipeitemforingredients_recipeitemid_key UNIQUE (recipeitemid)
If recipeItemId is unique, then of course, the tuple (recipeId, recipeItemId) is also unique.
Moreover, since the PK of the table is (recipeId, recipeItemId), the constraint is already applied by the PK constraint.