ON DELETE CASCADE not created when using dysl schema generation in Mysql

In Maven-Spring -Hibernate-MySql running on a Tomcat web application, I use hibernate ddl to create my DB schema using MySQL5InnoDBDialect.

The circuit is generated just fine, with the exception of the cascade option for foreign keys. For example, I have this structure:

A user object that contains a user part object, both use the same key:

@Entity @Table(name = "Users") public class User implements Serializable { private static final long serialVersionUID = -359364426541408141L; /*--- Members ---*/ /** * The unique generated ID of the entity. */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "User_Id") protected long id; @Getter @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "user", optional = true) protected UserDetails userDetails; ... } 

And user data:

 @Entity @Table(name = "UserDetails") public class UserDetails implements Serializable { private static final long serialVersionUID = 957231221603878419L; /*--- Members ---*/ /** * Shared Key */ @Id @GeneratedValue(generator = "User-Primary-Key") @GenericGenerator(name = "User-Primary-Key", strategy = "foreign", parameters = { @Parameter(name = "property", value = "user") }) @Column(name = "User_Id") protected long id; @Getter @Setter @OneToOne(optional = false, fetch = FetchType.LAZY) @PrimaryKeyJoinColumn private User user; ... } 

When creating a schema, a foreign key from the user information table to the user table skips cascading.

Here is a diagram for creating custom parts:

 CREATE TABLE `userdetails` ( `User_Id` bigint(20) NOT NULL, `Creation_Time` bigint(20) NOT NULL, `EMail` varchar(128) DEFAULT NULL, `Enabled` bit(1) NOT NULL, `First_Name` varchar(15) DEFAULT NULL, `Last_Name` varchar(25) DEFAULT NULL, `Password` varchar(64) NOT NULL, `User_Name` varchar(15) NOT NULL, PRIMARY KEY (`User_Id`), UNIQUE KEY `User_Name` (`User_Name`), UNIQUE KEY `EMail` (`EMail`), KEY `FKAE447BD7BF9006F5` (`User_Id`), CONSTRAINT `FKAE447BD7BF9006F5` FOREIGN KEY (`User_Id`) REFERENCES `users` (`User_Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$ 

As you can see, in the "FOREIGN KEY" section there is no "ON DELETE CASCADE".

This problem is also described here and here .

So I tried adding the @OnDelete annotation over the userDetails element with no luck.

Then I created my own dialect overriding supportCascadeDelete:

 public class MySql5Dialect extends MySQL5InnoDBDialect { public MySql5Dialect() { super(); } @Override public String getTableTypeString() { return " ENGINE=InnoDB DEFAULT CHARSET=utf8"; } @Override public boolean supportsCascadeDelete() { return true; } } 

But still unchanged. The foreign key cascade option is still set to "RESTRICT" after generating the scheme:

enter image description here

Is there a way to solve this problem (of course, not manually)?

UPDATE

Following Angel Villalain's suggestion , I put the @OnDelete annotation above the user member of the UserDetails class, and this did the trick for the OneToOne relationship, deleting is cascading, but OnUpdate is set to restrict (still), which leads me to my first question - what is the point of this ? I mean, "OnDelete" is pretty straight forward - when I delete a parent, I also delete it, but what is the meaning of the "OnUpdate" option? How does this affect my application when it is configured to restrict / cascade?

My second question is about cascading OneToMany relationships. The My User class contains many UserProviders. The following code is from the User class:

 @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) @JoinTable(name = "Users_Providers", joinColumns = @JoinColumn(name = "User_Id"), inverseJoinColumns = @JoinColumn(name = "Provider_Id")) protected Set<UserProvider> userProviders = new HashSet<>(0); 

And this is the inverse of the UserProvider class:

 @ManyToOne(fetch = FetchType.LAZY) @JoinTable(name = "Users_Providers", joinColumns = @JoinColumn(name = "Provider_Id", insertable = false, updatable = false), inverseJoinColumns = @JoinColumn(name = "User_Id")) @OnDelete(action = OnDeleteAction.CASCADE) protected User user; 

So, after using the @OnDelete annotation, I expected to see the onDelete parameter with a cascade in the connection table, but this is not so :( Did I use it correctly?

The final question is, what about a unidirectional relationship like @ElementCollection? My UserDetails class contains ElementCollection roles (each user can be assigned one or more roles):

 @ElementCollection(fetch = FetchType.EAGER, targetClass = Role.class) @CollectionTable(name = "Users_Roles", joinColumns = @JoinColumn(name = "User_Id", referencedColumnName = "User_Id")) @Column(name = "Role") protected Set<Role> roles = new HashSet<Enums.Role>(0); 

A role is just an enumeration, not an entity, so I cannot point from a role to a parent. In this case, is there a way to cascade onDelete?

+6
source share
2 answers

After exploring the problem, I came up with the following methods for handling DB schema generation (assuming you are using Hibernate as a JPA provider):

  • Using the ddl schema generation, you can create your own DB schema. Using this parameter, the scheme will be created / updated when your web server starts. If you use this method to make sure the onDelete parameter is set to cascade, you can use the OnDelete annotation. This worked just fine for me for the OneToOne relationship (thanks to Angel Villalain ), but for some reason it didn't work for the OneToMany relationship. To get around this gap, I used Spring ResourceDatabasePopulator :

enter image description here

The db-additions.sql file contains queries that adapt my database, in my case create an Ondelete Cascade. For instance:

 ALTER TABLE `buysmartdb`.`users_providers` DROP FOREIGN KEY `FKB4152EEBBF9006F5` ; ALTER TABLE `buysmartdb`.`users_providers` ADD CONSTRAINT `FKB4152EEBBF9006F5` FOREIGN KEY (`User_Id` ) REFERENCES `buysmartdb`.`users` (`User_Id` ) ON DELETE CASCADE ON UPDATE CASCADE; 

Note that the scripts triggered by the ResourceDatabasePopulator are applied after the schema is generated by Hibernate ddl, which is good. I know that due to the end result due to the chest I could not be sure that this is guaranteed.

  • The second method is to create a circuit using maven at compile time. There are several ways to do this, for example this one or that one.

Hope this helps someone ...

+2
source

When annotating, OnDelete DDL must be right. Could you check how you configure SessionFactory in the specific value that you use for the hbm2ddl.auto parameter.

UPDATE

  • Regarding your problem with the UserProvider class. At first, the display appears bidirectional, but one side should be the owner’s side and the other should be the back side. The value of who owns the relationship is the one that stores the relationship in the connection table, and the other must be mapped to the mappedBy parameter and not control the relationship. So OneToMany with mappedBy pointing to the user element UserProperty will be the back side, and UserProperty will be the owner side, and there should be an OnDelete annotation. But let me check it out tomorrow to be sure I'm not in front of my station.
+4
source

All Articles