i'm using hibernate annotations in my project,
I've created the tables and it's all good except that when i check the database their's no cascade even tho I've made sure to put it in the classes.
here is an exemple of how i do it :
i'm using mysql database, here's the hibernate.cfg.xml:
except that when i check the database their's no cascade
Not a very helpful description of the problem. Perhaps you could explain what behaviour you are expecting and what actually happens using a simple example. It may also be useful to see your EntityManager code.
Some of the attributes are used only for schema generation like your @Column(length = xxx) . Cascade is not one of those attributes. This is not used for schema generation, rather it defines how operations are propagated to the associated entity. This is different than adding a cascade on delete option on a database ddl. For example there is a CascadeType.PERSIST which clearly has no equivalent in a database schema.
okey so what attributes should i add to get the cascad option.
i forgot to add that i already tried
@OnDelete(action = OnDeleteAction.CASCADE)
I generally don't generate the ddl so I have not really had this issue, but It looks like @OnDelete should work for this, make sure it is on the parent entity, you can try explicitly defining the FK with @ForeignKey as well.
:s still no cascade but thank you for the links, learned a couple of new things .
i think i might do this manually (delete the parent befor the child object) their's so much changes that happen so the database should be possible to generate from the classes.
Using the cascade annotations are still beneficial. Not sure what you meant by do it all manually.
Just to throw a shallow example out there say I have a Person entity and an Address Entity. Say the Person has an Address.
One possible mapping might look something like this
Now without the CascadeType.PERSIST I would have to save the address before saving the person. Now I can just create the person set a new address on it and save the person. This will automatically save the address first for me, avoiding the need to call save on each of the objects. Of course there are the others you were talking about to:
CascadeType.REMOVE, Orphan remval and OnDelete. Even if it does not go in your ddl it can save you a lot of work in your code if you can call persist or delete and hibernate will take care of issuing the correct sql to persist or remove the associated entities.
Joined: Aug 17, 2012
but doesn't cascade = CascadeType.ALL cover them all (persist, remove ...). the reason why i'm cheking the DDL is because when i delete the adresse in your example (knowing that it's attached to a person)
I will end up with an foreing key error : Cannot delete or update a parent row: a foreign key constraint fails (`dac_bd4`.`item`, CONSTRAINT `FK317B1335EE5A98` FOREIGN KEY (`IDDIVISION`) REFERENCES `division` (`IDDIVISION`))
here is the entire error log:
when i said i'll do it manually i mean befor deleting the adresse i'm going to delete every person that has that adresse then delete the adresse (i realise it's not the best way to do it :s ... ).
thank you for your time!
Edit - Removed long lines to prevent horizontal scrolling
If your cascade works correctly, you won't need to delete the address after deleting the person. The first delete should delete both entities. This is assuming no other person is linked to the address.
Joined: Aug 17, 2012
that precisely the probleme, cascade is not working and i can't figure out why!
You are trying to delete an Item which has a ManyToOne relationship with a Division - meaning more than one Item can refer to the same Division. On this relation, you have also defined a Cascade type of ALL. The error you are getting is because another Item (or multiple Items) refers to the Division you are trying to delete - via the cascade when deleting an Item.
Either your relation is incorrect or you need to change your cascade type.
Joined: Aug 17, 2012
actualy a get the error when i try to delete the division and yes many item can refere to the same division so when i try to delete a division all the items atached to it are deleted as well.
change my cascade type to what exactly? like i'v said i alredy tried a few and no luck.
excuse my questions, this is my first time with an ORM
Ok, so you have no cascade defined in Division for Item. This explains why when you attempt to delete a Division, no cascade occurs but the error is raised because one or more Items refers to the Division you are attempting to delete. You cannot expect anything to happen to your Items when you delete a Division unless you define it as such in the Division class.
I believe the only way to do this is to apply a OneToMany relation in Division for Item with a cascade type of ALL and DELETE_ORPHAN.
but doesn't cascade = CascadeType.ALL cover them all
It does not include orphan removal that is different.
Ill be honest I typically use JPA with hibernate as the persistence provider thusly I only use the cascade options from that javax.persistence package only.
You need to be careful with REMOVE
The cascade REMOVE operation really only makes sense on one-to-one and one-to-many relationships where there is a clear parent-child relationship. What I mean by that is even if it is a one-to-one or a one-to-many if the target is participating in other relationships or can stand alone it probably does not make sense to use REMOVE.
That said consider the following.. (Note that if the owning side is safe for REMOVE it is probably also safe to use PERSIST however the inverse is NOT necessarily true)
This will remove the Employee and his cubicle. Cascade.REMOVE can only safely be cascaded from parent to child. Trying to remove the Cubicle directly will result in an integrity constraint violation unless I first set reference to the Cubicle in the employee object to null. Setting the REMOVE cascade option on the @OneToOne annotation in the Cubicle object would not cause it to be removed from the Employee rather it would have the undesirable affect of removing the employee. As you know removing a cubicle should not remove the employee.
Hope this clears things up for you.
Joined: Aug 17, 2012
okey so i'm back, i tried to apply a OneToMany relation in Division for Item like james said but it didn't change anything i'm still getting that Cannot delete or update a parent row error, i alse made sur i have the CascadeType.Persist
here is how it looks now
OK I am not sure if you just did not read my last post or if you did not understand it.
As James said lets simplify this and keep it just about Cascade.REMOVE for moment.
Say you have this in your Division (Note that having both CascadeType.ALL and cascadeType.REMOVE is redundant)
Now like you example lets have this for Item
Now lets take a look at a simple example.
Ok so far so good. Now lets try to delete an Item. This is where I think you ignored my last post
Ok so to summarize. Running this with the Cascade.REMOVE on the @ManyToOne has the undesirable effect of deleting all the items and the division!! Taking the cascade.Remove off will result in an exception. Lets modify the code now so that it will work. It now looks like this. The cascade rules are the same on the @OneToMany
Ok now hopefully you understand Cascade.Remove.
Lets talk about orphan removal. Orphan removal should only be used on a very specific type of parent child relationship. It can only be added on @OneToMany and @OneToOne.
Orphan removal rules:
rule1 - child entity may only be a child of one parent entity, and may not ever belong to a different parent.
rule2- the child entity can not exist without its parent.
The the orphanRemoval element causes the child entity to be removed when the relationship between the parent and the child is broken. This can be done in 2 ways
1 setting to null the attribute that holds the related entity
2. in the one-to-many case you can remove the child entity from the collection.
The provider is then responsible for removing the orphaned child entity.
Just for the sake of being totally complete lets talk about @OnDelete(action = OnDeleteAction.CASCADE) . By the way I tested this an on my machine it DOES put a cascade delete constraint on the generated DDL. This is actually required for it to work properly. Note this is a hibernate specific annotation and not a JPA one.
So looking at the code below:
When entityManager.remove(division); is executed there will be 4 SQL delete statements executed one on the division and 3 on the Item table.
Now if we add that annotation to our relationship.
That same code will execute only one delete statement on the division table. Since the cascade constraint is assumed to be in the ddl the referenced rows in the Item table will be removed along with it.
Joined: Aug 17, 2012
if i remove the annotations from item like this:
the type of the feild division created in the ddl is tinyblob :s and their for it is not recongnised in my program!
oh and when i try to use it with the old database, then i can't list the divisions using SessionFactory.getCurrentSession().createQuery("FROM Division").list();
in both cases i get
août 26, 2012 10:44:27 AM org.hibernate.type.NullableType nullSafeGet
Infos: could not read column value from result set: division2_0_; could not deserialize
août 26, 2012 10:44:27 AM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
Grave: Error Rendering View[/listDivision.xhtml]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DivisionBean': Invocation of init method failed; nested exception is org.hibernate.type.SerializationException: could not deserialize
i'm starting to think their must be somthing else that i am doing wrong, that causes the child entitys not to be deleted with the parent entity. is their any other reason that can cause this problem?
One last bit of advice for you. Joshua Bloch author of Effective Java was asked if he could give one piece of advice to software developers what would it be? He responded "when in doubt leave it out". Apply this advice to cascade rules as well. It is so easy to just write CascadeType.ALL but that is many times not what you want. Add them one by one when you need them. If you end up needing them all then you can save yourself a little verbosity and add the CascadeType.ALL rule.