【问题标题】:Hibernate not preserving referential integrityHibernate 不保留参照完整性
【发布时间】:2017-12-30 23:22:50
【问题描述】:

在休眠中,我在用户和角色之间创建了一对多的关系。 一个角色可以关联多个用户,但一个用户只能关联一个角色。

在用户类中,我有

            @ManyToOne
            @JoinColumn(name = "role_id")
            private Role role_id;

在角色类中,我有

    @OneToMany(mappedBy="role_id", fetch=FetchType.LAZY)
    private Collection<User> userList = new ArrayList<User>();

如果我将新用户保存为:

{
"userName" : "Michael",
"role_id" : {
              "id" : 8    
            }
}

即使角色表没有 id 为 8 的角色(并且角色表中没有任何条目),它也会保存用户。 我希望每当我保存具有不存在角色的用户时,我应该得到一个参照完整性错误。 我应该改变什么?

我的用户表创建为:

CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) DEFAULT NULL,
  `mobile` varchar(255) DEFAULT NULL,
  `username` varchar(255) NOT NULL,
  `role_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_abcdef` (`role_id`),
  CONSTRAINT `FK_abcdef` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

【问题讨论】:

  • 请告知您究竟是如何持久化实体的?

标签: java hibernate orm


【解决方案1】:

您在数据库中的表中是否有 FK 约束?如果您使用 mySql,也许 this 可以帮助您。或者您也可以自行在数据库中设置限制。

【讨论】:

  • 谢谢loannis,但我设置了外键约束。请查看更新后的答案
【解决方案2】:

在您的@OneToMany 注释中,您可能需要添加targetEntity = User.class。这是因为以下原因:

  1. java泛型使用类型擦除,这意味着在生成的字节码中,你的userListCollection类型,而不是Collection&lt;User&gt;类型。所以,hibernate 不知道目标实体是什么,除非你明确告诉它。

  2. Hibernate 通常喜欢遵循静默错误/隐藏错误的方法,这意味着它会在问题发生的那一刻(例如,它不知道您的集合元素是什么类型的那一刻)静默地忽略问题,并稍后失败,当问题的原因不再很清楚时。 (例如,当您执行一个应该失败但它没有失败的查询时,或者您执行一个应该获取某些内容但它什么也没获取的查询。)

  3. 从 java 9 开始,编译器确实存储了在生成的 .class 文件中创建泛型字段时使用的实际类型参数的信息,并且可以使用反射发现该信息,但我不是知道休眠已更新以检查此信息。

【讨论】:

  • JPA 规范要求 targetEntity 仅用于原始集合,它应该能够获得泛型类型。我认为这不是必需的。
  • @fg78nc 如果是这样,我将删除我的答案。但我相信这就是它在过去对我有用的原因,我看到很多代码使用 targetEntity 而没有原始集合,所以我当然希望 OP 试一试。
  • 我刚刚说过targetEntity 的目的是按照规范收集原始集合。如果它对你有用,那很好,让他试试。
猜你喜欢
  • 2010-09-26
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-13
  • 2013-09-14
  • 1970-01-01
相关资源
最近更新 更多