I want to make sure I understand what I am doing in my DB representation & with hibernate.
My project management tool lets my user create a Project that is composed of Phase(s).
I do not wish to create a link table and have proceeded like such in my entities:
My ProjectEntity:
#OneToMany(mappedBy = "id")
private Set<PhaseEntity> phases = new HashSet<>(0);
and my PhaseEntity:
#NotNull
#ManyToOne(targetEntity = ProjectEntity.class)
private ProjectEntity project;
After filling up my PhaseEntity and saving it via my DAO
phaseDao.save(phaseEntity);
I get the following error:
ERROR: insert or update on table "phase" violates foreign key constraint "fk8x1x98c4hq4ps0d30y6nxe90u"
Detail: Key (phase_id)=(1820) is not present in table "project".
The way I see it, pushing a phase containing a specific ProjectEntity to my database should create 1 entry and update another one, the first should be my phase entry, and the latter should be an update to a project by adding a phase to its Set.
Do I have to explicitly save my phase in my project table?
Do yo see any flaws in my reasoning?
Just sharing the knowledge!
"a Project that is composed of Phase(s)"
So , if you want to insert a phase in "Phase" table, you need to have a role in Project table which has the same 'class' column value as "class" column value of newly inserted row in Phase table.
A foreign key is a column (or columns) that references a column (most often the primary key) of another table. The purpose of the foreign key is to ensure referential integrity of the data. In other words, only values that are supposed to appear in the database are permitted.
We have two tables, a Project table that includes all projects, and a Phase table that includes all phases. A Project that is composed of Phase(s). To enforce this logic, we place a foreign key on the Phase table and have it reference the primary key of the Project table. This way, we can ensure that all phases in the Phase table are related to a project in the Phase table. In other words, the Phases table cannot contain information on a project that is not in the Project table.
Related
I have a #ManyToOne relation between Workpackages and Projects. Where a project can have one to many workpackages.
My Workpackage entity refers to the Project one like such:
#NotNull
#ManyToOne(targetEntity = ProjectEntity.class)
private ProjectEntity project;
Therefore each line in my Workpackage table references the id of a certain project.
But when I try to delete a project, I get a foreign key constraint (which makes sense, since my workpackage depends on a project, and should be deleted before the former is deleted).
But a cascade = CascadeType.REMOVE won't work since I am deleting my project and not my Workpackage. Would there be a way to delete the Workpackage related to a certain project upon its deletion?
Being new to Hibernate, nothing obvious comes to mind other than going through every Workpackage and deleting them one by one.
ON DELETE CASCADE : if you delete a project row in table Project the engine will delete as well the related workPackages. This can used to make automatic cleanups on secondary tables.
When declaring schema, do the following thing
alter table Workpackage add constraint constraintName
foreign key (id) references Project(id) on delete cascade
you will have to set child's object as null explicitly.
for (Workpackage child : project.getWorkpackages()) {
child.setProject(null);
}
session.delete(OwningSide);
We have two copies of a simple application that is based on SQLite. The application has 10 tables with a variety of relations between the tables. We would like to merge the databases to a single Postgres database with the same schema. We can use Talend to facilitate this, however the issue is that there would be duplicate keys (as both the source databases are independent). Is there a systematic method by which we can insert data into Postgres with the original key plus an offset resulting from loading the first database?
Step 1. Restore the first database.
Step 2. Change foreign keys of all tables by adding the option on update cascade.
For example, if the column table_b.a_id refers to the column table_a.id:
alter table table_b
drop constraint table_b_a_id_fkey,
add constraint table_b_a_id_fkey
foreign key (a_id) references table_a(id)
on update cascade;
Step 3. Update primary keys of the tables by adding the desired offset, e.g.:
update table_a
set id = 10000+ id;
Step 4. Restore the second database.
If you have the possibility to edit the script with database schema (or do the transfer manually with your own script), you can merge steps 1 and 2 and edit the script before the restore (adding the option on update cascade for foreign keys in tables declarations).
I am using VS2012 and the Entity designer to generate both the database and the models. I have a very basic scenario of Table1 to Table1and2JoinTable to Table2. Something like Students, Classes, StudentClasses. You can have many students in many classes. I would like to have a cascading delete. So if you delete a student any rows in the StudentClass join table are deleted for that student id. Same for deleting a class any rows in the StudentClass are deleted for that class id. After setting up the many to many association in the designer and setting the cascade delete options you get the following error when you attempt to generate the database:
Error 132: End 'Student' on relationship 'Model1.StudentClass' cannot have operation specified since its multiplicity is ''. Operations cannot be specified on ends with multiplicity ''.
Here is a small example:
Here is the association created:
And the resulting error messages:
Here is a portion of the SQL code for generating the database tables:
-- Creating foreign key on [Students_Id] in table 'StudentClass'
ALTER TABLE [dbo].[StudentClass]
ADD CONSTRAINT [FK_StudentClass_Student]
FOREIGN KEY ([Students_Id])
REFERENCES [dbo].[Students]
([Id])
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- This should be ON DELETE CASCADE ON UPDATE NO ACTION;
GO
-- Creating foreign key on [Classes_Id] in table 'StudentClass'
ALTER TABLE [dbo].[StudentClass]
ADD CONSTRAINT [FK_StudentClass_Class]
FOREIGN KEY ([Classes_Id])
REFERENCES [dbo].[Classes]
([Id])
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- This should be ON DELETE CASCADE ON UPDATE NO ACTION;
GO
I know how to work around this by just editing the database script and add in the on delete cascade option. But, I don't want to do this because I am going to come back to the designer many times as the project grows and I don't want to have to remember this step every time.
Has anyone figured out how to resolve this?
It seems to be an edmx restriction, which I don't really understand. Code-first is perfectly capable of generating a junction table with two cascading ON DELETE constraints, but model-first and database-first do not allow the same configuration in the edmx. Normally, cascade actions are configured on the 'one' end of an association. Maybe it is too complex to check the validity of cascade actions on '*' ends (only when both ends are '*').
For the cascaded delete to happen with a context based on an edmx model, you have to load a parent and its children and then delete the parent.
var cls = db.Classes.Include(c => c.Students).Single(c => c.Id = 1);
db.Classes.Remove(cls);
db.SaveChanges();
The executed SQL statements show that the Class is fetched from the database in a JOIN statement with Student. Then the StudentClasss and the Class are deleted respectively.
Obviously, this is much more expensive than enabling cascaded delete in the database.
The work-around to modify the DDL each time after is was generated is not attractive, of course. But I think the only alternative is to make StudentClass part of the model and configure cascaded delete on the 'one' ends of the new associations. Or go code-first.
First of all make sure that you have an ON DELETE CASCADE specified in your Foreign Keys on database side.
I had similar problem and just adding ON DELETE CASCADE solve it instead of setting End1OnDelete and End2OnDelete properties.
I have a junction table with and idenity primary key columns to realize a many to many relationship. Visual Studio automatically detects it as a many to many relationship and the junction table is not an entity.
How can i realize it that also this table is generated as an entity? I need this for breeze.js .
You just need to add additional columns (or properties) to that table (or model).
You said that your table has acolumn named ID and it's the primary key withe IsIdentity set to true. It must works, I'm using this approach...
There must be a problem or missing with your table definition. However, if all are OK, just add a nullable column in your table and update your model from database. The problem will go away.
I have two tables
Users
Users_Role
I decided to try to add a foreign key as to my understanding it will let me cascade the delete procedure when removing a user from Users (as well as enforce integrity).
So via Management Studio I right clicked my Users_Role table, Design, then went into Relationships. I added a new relationship between the two tables as such:
Foreign Key Base Table: Users_Role
Foreign Key Columns: UserID
Primary/Unique Key Base: Users
Primary/Unique Key columns: ID
When I then try to save, I get the following error:
'Users' table saved successfully
'Users_Role' table
- Unable to create relationship 'FK_Users_Role_Users'.
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Users_Role_Users". The conflict occurred in database "db", table "dbo.Users", column 'ID'.
I'm not sure what's going on. Adds the relationship to Users, but not Users_Role? The only thing special about Users_Role is that my primary key consists of two columns, UserID and Role (the only two columns in the table, if that matters). Otherwise, nothing special.
This error means that in your current database, you have entries in the "Users_Role" table which have a "UserID" value that is not present in the Users table as ID.
You first need to find those "rogue" rows and either update or delete them, before you can create the foreign key to enforce referential integrity and avoid such problems in the future.
You can find those by issuing this command:
SELECT * FROM Users_Role
WHERE UserID NOT IN
(SELECT DISTINCT ID FROM Users)