Tomcat Web アプリで実行されている Maven-Spring-Hibernate-MySql では、hibernate ddl を使用して、MySQL5InnoDBDialect で DB スキーマを生成しています。
スキーマは、外部キーのカスケード オプションを除いて問題なく生成されます。たとえば、私はこの構造を持っています:
ユーザー詳細オブジェクトを保持するユーザー オブジェクト。両方とも同じキーを共有します。
@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;
...
}
そしてユーザーの詳細:
@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;
...
}
スキーマの生成時に、users-details テーブルから users テーブルへの外部キーにカスケードがありません。
ユーザー詳細のスキーマ作成は次のとおりです。
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$$
ご覧のとおり、「FOREIGN KEY」セクションに「ON DELETE CASCADE」とは書かれていません。
そこで、userDetails メンバーの上に @OnDelete アノテーションを追加しようとしましたが、うまくいきませんでした..
次に、supportsCascadeDelete をオーバーライドする独自の方言を作成しました。
public class MySql5Dialect extends MySQL5InnoDBDialect {
public MySql5Dialect() {
super();
}
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
@Override
public boolean supportsCascadeDelete() {
return true;
}
}
でも相変わらず変化なし。スキーマを生成した後も、外部キーのカスケード オプションが "RESTRICT" に設定されています。
この問題を解決する方法はありますか (もちろん手動ではありません)。
アップデート
Angel Villalainの提案に従って、 @OnDelete アノテーションを UserDetails クラスの「ユーザー」メンバーの上に配置しました。これにより、OneToOne 関係のトリックが行われました。削除はカスケードされますが、OnUpdate は制限するように設定されています (まだ)。私の最初の質問に私に-それはどういう意味ですか? 「OnDelete」は非常に簡単です。親を削除すると子も削除されますが、「OnUpdate」オプションの意味は何ですか? 制限/カスケードに設定すると、アプリにどのような影響がありますか?
2 番目の質問は、OneToMany 関係でのカスケードに関するものです。私の User クラスは多くの UserProvider を保持しています。次のコードはUserクラスからのものです。
@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);
そして、これはUserProviderクラスからの逆の関係です:
@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;
したがって、 @OnDelete アノテーションを使用した後、結合テーブルでカスケードを使用して onDelete オプションが表示されることを期待していましたが、そうではありません:(正しく使用しましたか?
最後の質問 - @ElementCollection などの一方向の関係はどうですか? 私のUserDetailsクラスは、役割の ElementCollection を保持します (各ユーザーには 1 つ以上の役割を割り当てることができます)。
@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);
ロールは単なる列挙型であり、エンティティではないため、ロールから親エンティティを指すことはできません。この場合、onDelete をカスケードする方法はありますか?