Many-To-One hibernate delete the many when delete the one? - mysql

I have two classes
Account
id.
....
Invoice
id...
....
account_id (many to one)
As many invoices exist for one user, and it requires a User, I wrote it as many to one in invoice.
Cascading I believe means if I delete an Invoice then it will affect the account, by trying to add update/delete etc.
However to delete an account there are foreign key which means it cannot be deleted, unless I remove all invoices first.
A workaround is having a one to many/joining table in account, but I would rather have many to one as a invoice requires an account.
Is there a setting i could put in the orm to mean:
If I delete a Invoice nothing happens to account.
If I delete an account ALL the invoices linked to it are deleted
currently::
<many-to-one name="account" fetch="EAGER"
target-entity="UserAccount">
<join-column name="account_id"/>
<cascade><cascade-all/></cascade>
</many-to-one>

Yes. Map a OneToMany in Account to Invoice. You are mistaken when you thought it needed a join table - it does not. Based on you wanting to have a Invoice->Account ManyToOne relationship, you can just reuse this relationship:
#Entity
Class Account {
#OneToMany(cascade=ALL, mappedBy="account")
List<Invoice> invoices;
}
#Entity
Class Invoice{
#ManyToOne
Account account;
}
These settings mean the if you delete an Account, JPA will delete all referenced invoices as well. Since there are no cascade settings on the Invoice.account relation, deleting an Invoice does not affect the account. That said, you should remove the invoice from the Account.invoice collection when you are deleting an invoice instance. JPA does not maintain bidirectional relationships for you, so when you modify one side of a bidirectional relationhip, you are required to modify the other side as well to keep your object model in sync with the database - JPA allows for caching which won't reflect the database if you don't.
There are many tutorials you could look at for this relationship, but the simplest explaination I've found is:
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Relationship_Mappings/Collection_Mappings/OneToMany
If you don't want it to be Bidirectional (ie you don't want the Invoice.account reference), I believe JPA 2.0 allows you to use a #JoinColumn annotation on the OneToMany:
#Entity
Class Account {
#OneToMany(cascade=ALL)
#JoinColumn(name="account_id")
List<Invoice> invoices;
}

One thing that I can suggest is to set cascading delete in the foreign key relationship in the database. That way when an account is deleted all the related invoices will be deleted easily.

Related

Prevent delete if object in some collection

In SQLAlchemy is it possible to prevent (or specifically raise a custom Exception) the deletion of an object that is part of a collection in a many-to-many relationship.
For example below I have a Party and Person. Any Party can have many Persons and any Person can go to many Parties.
If a Person is recorded as going to one or more Parties I want to prohibit that Person from being deleted.
party_person_ass_table = db.Table('party_person', db.Model.metadata,
db.Column('party_id', db.ForeignKey('party.id'), primary_key=True),
db.Column('person_id', db.ForeignKey('person.id'), primary_key=True))
class Party(db.Model):
...
people = db.relationship('Person', secondary=party_person_ass_table, back_populates='parties')
class Person(db.Model):
...
parties = db.relationship('Party', secondary=party_person_ass_table, back_populates='people')
Reading the docs it seems cascade deleting from the secondary table is automatically set (https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html). I wonder if a solution to generate an IntegrityError would be to add a nullable=False to the person_id column in the secondary association table and then somehow prevent a cascade delete from impacting the secondary table?
adding the tag viewonly=True to:
parties = db.relationship('Party', secondary=party_person_ass_table, back_populates='people', viewonly=True)
decouples Person from the party_person_ass_table and when modified it does not automatically delete the row in the association table, which breaks database integrity.
This is also why the commented 'ON DELETE RESTRICT' fails because it isnt an inherent cascade, but SQLAlchemy specifically deletes these rows as part of its function so these hooks aren't called in the usual way.

Hibernate Bidirectional or two unidirectionals relations

I have two entities Users and Groups , associated with Many-To-Many
a user belongs to many groups and he know them (navigabilite_1)
a group contain many users and he know them (navigabilite_2)
I want when I delete a user only user and the relation(in join table) get deleted not the group and the same for deleting groups should not affect user only the group and the relation
What kind of association should I use Bidirectional or two unidirectional ,and where should I put the cascade on delete ?
You should use a bidirectional association, and you shouldn't use any cascade, since cascading would also delete the entity at the other side of the association.
Assuming User.groups is the owner side of the association, deleting a group would be done using
for (User user : group.getUsers()) {
user.getGroups().remove(group);
}
// optional:
group.getUsers().clear();
session.delete(group);
And deleting a user would be done using
// optional:
for (Group group : user.getGroups()) {
group.getUsers().remove(user);
}
user.getGroups().clear();
session.delete(user);

Laravel 4.0 cascade delete and polymorphic relations

I am using the Eloquent plymorphic relations and the ON DELETE CASCADE option of mysql, and am afraid of how my data will stay consistent over time. Let me explain:
If I have a model Room which contains furnitures of several types (morphMany of Table, Chair, Couch...), and that I decide to delete it, his related furnitures won't get deleted.
To solve this issure I handled the deletion of the related furnitures in the delete event of the Room model, but this event won't necessarily get fired all the time.
Let's say that I have an other model called House, containing several rooms (hasMany). If I decide to delete it, its related models will deleted by mysql with the ON DELETE CASCADE option. I will then stay with data in my tables tables, chairs, couchs that are not relevant anymore, and not related to any row of the rooms table anymore.
So what is the best way to keep a database consistent with ON DELETE CASCADE and the Eloquent's polymorphic relations?
If you're using the raw database (cascading) approach, that bypasses Eloquent and it becomes impossible to do what you want.
Set up a deleted event for House which iterates through all its Rooms and deletes those, which again triggers the Room's deleted events.

Spring Roo - many to many relationship deletes and inserting at every update- How to change this behavior

I have two entities created.
Entity BOOK, Entity AUTHOR having many to many relationship.
In the db I got tables [book,author, book_author].
Table book_author maps the many to many relationship.
When I update authors of a book all related relationship records in book_author
get deleted and then get re-inserted.
Is there a way to alter this behavior to do updates as necessary, without doing
delete and re-insert.
By the no modification have been done manually. All the code have been done with ROO.
It is the default behavior if "List" is used as the collection to keep relationship
in the entity level. Instead we can use a "Set" which will make updates and deletes as
necessary without doing delete and re-insert.
This is clearly explained in the following article.
http://assarconsulting.blogspot.com/2009/08/why-hibernate-does-delete-all-then-re.html

Many-to-One and One-to-One Relationships on Same Two Tables?

I'm designing a database where two fields have a many-to-one relationship, but I also need a one-to-one relationship between them, and I would like some advice on whether there is a better way to do it than what I've got right now.
My tables are accounts and users. An account can have multiple users, but each account can only and must have one owner. A user can be related to only one account.
I have an account field in the users table, which stores the ID of the account the user is related to. In the accounts table, I have an owner field, which stores the ID of the user who owns the account (i.e. the head admin).
I'm using InnoDB so I can make use of foreign keys. The problem is that I can't create an account or a user without the other being created first (due to the restraints of the foreign keys), so I made owner nullable. Now I can create an account with a null owner, then create the user, and finally set the owner on the account to the user.
Is this acceptable, and is there a better way?
Here are some possible other ways I've come up with, and my thoughts on each:
Have a boolean owner field in the users table. Since every account can only have one owner, this way seems less than ideal because I'd have to ensure only one user per account has the attribute set to true.
Have a third table called owners. This seems like more overhead and more work for no good reason since it's effectively the same as having an owner field in the users table.
How I have it now makes the most sense to me, but it's a little awkward having to set a null owner until I create the user, and then coming back to set it after the fact.
I'd appreciate any input you can give me. Thanks!
This question is similar, but there's no mention of foreign keys: Designing Tables: One to many and one to one at same time?
In general is a bad idea if your schema cannot be sorted topologically, i.e. if you cannot establish an ordering where a table only refers to tables preceding it in the ordering. This sort of "layered" dependency is also a very nice property to have for example for software modules (you have a problem if two modules depends on each other).
In your case you have user that refers to account and account that refers to user so clearly there's no way to find a topological ordering.
One standard solution in this case is to introduce a separate table e.g. "role" where you have three columns: user, account and role. The column role can be either "owner" or "guest".
The fact that you know that (given the current requests) an account must have one and only one owner, or that a user must be listed in one and only one account are not IMO rules that are really pertinent to the domain of "users" and "accounts".
You can implement those rules easily, but structuring your data so that you have no other possibility is IMO a mistake. You should aim to model the domain, not the specific rules... because people will change their mind about what those rules are.
Can you conceive a user with two accounts? Can you conceive an account with multiple owners/admins? I can... and this means that most probably quite soon this will be a request. Structuring the data so that you cannot represent this is looking for troubles.
Also when you have cyclical dependencies in the model your queries will be harder to write.
A very common case is for example to try to represent a hierarchical part list database using just one table with a "parent" field that points to the table itself... much better is having two tables instead, part and component, where component has two references to part and and a quantity.
Your solution is fine.
If you're uncomfortable with the owner column being nullable, you could rely on some magic user record (perhaps with an id of zero) which would be the "system user". So newly created accounts would be owned by user-zero, until their ownership was suitably redefined. That seems smellier than allowing accounts to have a null owner, to me, anyway.
For the current requirement to have only one account per user
alter table UserAccount add constraint un_user_account unique(UserID);
and when the requirement changes to many-to-many, drop the constraint
alter table UserAccount drop constraint un_user_account;
For the one owner only, simply enforce that on the application level.