当前位置: 首页 > 知识库问答 >
问题:

在Mysql上使用ddl模式生成时未生成的ON DELETE CASCADE选项

华凡
2023-03-14

在Tomcat web应用程序上运行的Maven-Spring-Hibernate-MySql中,我使用hibernate ddl生成带有mysql5InnodbDealication的DB模式。

除了外键的cascade选项外,模式的生成很好。例如,我有这样的结构:

保存用户详细信息对象的用户对象,两者共享相同的键:

@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;

...

}

下面是用户详细信息的模式创建:

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$$

正如您所看到的,在“外键”部分中没有写任何“on DELETE cascade”。

这个问题也在这里和这里描述以及。

然后,我创建了自己的方言,覆盖了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类的“user”成员上方,这就解决了OneToOne关系的问题,delete被级联,但OnUpdate被设置为restrict(still),这就引出了我的第一个问题--这是什么意思?我的意思是“ondelete”非常直接--当我删除父级时,也删除子级,但“onupdate”选项的含义是什么?当我的应用程序设置为限制/级联时,它如何影响它?

我的第二个问题指的是与一个整体关系的级联。我的User类包含许多UserProviders。以下代码来自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注释后,我希望在联接表中看到带有cascade的onDelete选项,但它不是:(我使用正确吗?

@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);

共有1个答案

王经赋
2023-03-14

使用ondelete注释,DDL应该是正确的。您是否可以检查您如何配置SessionFactory,特别是您为hbm2ddl.auto参数使用的值。

更新

  • 关于UserProvider类的问题。首先,映射似乎是双向的,但一方必须是所有者一方,另一方必须是逆方。也就是说,拥有关系的一方是将关系保存到联接表中的一方,而另一方必须使用mappedby参数映射,并且不控制关系。因此,OneTomanyMappedby指向UserPropertyUser成员的OneTomany将是相反的一面,UserProperty将是所有者的一面,并且应该有OnDelete注释。但让我明天测试一下,我不在我的开发站前面。
 类似资料:
  • DB2 RazorSQL生成DDL是用于创建用于创建该表的SQL命令。在DB2 RazorSQL生成DDL,可参考以下操作: 生成结果如下:

  • 我正在使用swagger 2和open api 5.3.1生成器生成一些类。目前,它似乎没有在Long(swagger中定义为int64)上生成模式注释。我该怎么做? 昂首阔步: 生成的代码

  • 问题 你需要准备一个复杂的、多部分的对象,你希望操作不止一次或有不同的配置。 解决方案 创建一个生成器封装对象的产生过程。 Todo.txt 格式提供了一个先进的但还是纯文本的方法来维护待办事项列表。手工输入每个项目有损耗且容易出错,然而 TodoTxtBuilder 类可以解决我们的麻烦: class TodoTxtBuilder constructor: (defaultParamet

  • 亦称: 建造者模式、Builder 意图 生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 问题 假设有这样一个复杂对象, 在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。 这些初始化代码通常深藏于一个包含众多参数且让人基本看不懂的构造函数中; 甚至还有更糟糕的情况, 那就是这些代码散落在客户端代码的多个位置

  • 有没有办法从Apache spark生成无模式的avro?我可以看到一种使用apache avro库通过Java/Scala和融合avro生成它的方法。当我用下面的方式从Spark编写Avro时,它用模式创建了Avro。我想在没有模式的情况下创建,以减少最终数据集的大小。

  • 但我得到以下错误: 已迁移到新包的该类: 然而,我没有找到在MAVEN Build中继续生成DDL创建脚本的明确方法。 那又怎样?它不是应该支持的一个主要特性吗?怎么做?