【问题标题】:Hibernate annotation: one-To-one onDelete action cannot set to CASCADEHibernate 注释:一对一的 onDelete 操作不能设置为 CASCADE
【发布时间】:2012-09-09 10:12:15
【问题描述】:

我想创建两个表 USER 和 USERDETAIL 来实现:

  1. USERDETAIL 引用了 USER 表。

  2. 对 USER 表的操作不需要知道 USERDEAIL 表的存在。

这应该是一对一的非双向关系。

实体类:

@Entity
@Table(name="USER")
public class User implements Serializable{  
    @Id 
    @Column(name="ID")
    @GeneratedValue(generator = "system-uuid") 
    @GenericGenerator(name = "system-uuid", strategy = "uuid")  
    private String id;  
    //...
}

@Entity
@Table(name="USERDETAIL")
public class UserDetail implements Serializable{    

    @Id 
    @Column(name="ID")
    @GeneratedValue(generator = "gen") 
    @GenericGenerator(name = "gen", strategy = "foreign",
    parameters = @Parameter(name = "property", value = "user"))
    private String id;

    @OneToOne(optional= false , targetEntity=User.class, cascade= CascadeType.ALL)
    @OnDelete(action = OnDeleteAction.CASCADE)
    //@JoinColumn(name="foreign_id",referencedColumnName="ID")
    @PrimaryKeyJoinColumn   
    private User user;  
    //...
}

这会正确创建两个表,并且 USERDETAIL 具有外键约束,即其主键由 USER 的 id 引用。但是,删除操作是Restrict,而不是Cascade。因此,我无法删除一行 USER。

我正在使用 MySQL 服务器 5.1。似乎它不支持级联删除操作。因为我可以手动删除约束并添加一个设置为 on delete 的新约束是级联的,并且可以按预期工作。

【问题讨论】:

    标签: database hibernate annotations hibernate-mapping cascade


    【解决方案1】:

    你的代码应该是:

    @Entity
    @Table(name="USER")
    public class User implements Serializable{  
        @Id 
        @Column(name="ID")
        @GeneratedValue(generator = "system-uuid") 
        @GenericGenerator(name = "system-uuid", strategy = "uuid")
        private String id;  
        //...
    
        @OneToOne(cascade = CascadeType.ALL)
        @JoinColumn(name="userdetail_id")
        public UserDetail getUserDetail() {
          ...
        }
    }
    
    @Entity
    @Table(name="USERDETAIL")
    public class UserDetail implements Serializable{    
    
        @Id 
        @Column(name="ID")
        @GeneratedValue(generator = "gen") 
        @GenericGenerator(name = "gen", strategy = "foreign",
        parameters = @Parameter(name = "property", value = "user"))
        private String id;
    
        @OneToOne(optional= false , targetEntity=User.class, mappedBy = "userDetail")
        @PrimaryKeyJoinColumn   
        private User user;  
        //...
    }
    

    基本上,我建议将其设为双向,User 类是所有者(通过在 UserDetail 类中使用 mappedBy)。这样,当您删除用户时,将删除用户详细信息。

    【讨论】:

    • 很抱歉没有提供足够的信息。因为用户类也将是表单输入提交的命令对象。我不想将整个用户详细信息放入编辑表单中。这就是我不想参考用户类的原因。
    • 您可以将这些 UserDetail 表单字段设置为隐藏吗?或在将对象作为命令对象提供之前对其进行修改。
    • 是的,我可以将字段设置为隐藏。但是为了保持关系,将整个对象注入到编辑表单中是不是有点太过分了?提交表单不需要更改 userdatil 表。
    • 嗨,我发现文件说:You don't have to (must not) define any physical mapping in the mappedBy sidehere。也许您可以删除 User 中的属性并在 UserDetail 中仍然使用mappedBy
    • 于。你好。我试过了,但它会在用户表上创建一个新列来引用 UserDetail。因此,我谨慎行事。将 mappedBy 和 PrimaryKeyJoinColumn 放在 User 类上。创建了一个新列来引用用户,它是还原的,因为我希望主键也是用户的外键引用。最重要的问题是 onDelete 操作仍然是 Restrict,因此我仍然无法删除 User 上的一行。
    【解决方案2】:

    我终于解决了这个问题。

    首先,我已经关注http://www.mkyong.com/hibernate/hibernate-one-to-one-relationship-example-annotation/创建oneToOne映射实体。

    但是,当我启动 Tomcat 时,它总是在映射时抛出 NullPointerException。因此,我提出了我的问题实体,除了删除之外似乎工作正常。

    我终于意识到这只是 hibernate-anoatation 导致的一个错误。然后我使用 3.4.0.ga 版本并再次点击链接。通过替换@GeneratedValue(strategy = IDENTITY)(不知道为什么用这个,hibernate不能创建表)来

    @GeneratedValue(generator = "system-uuid") 
    @GenericGenerator(name = "system-uuid", strategy = "uuid") 
    

    它按我的预期工作。

    虽然表上没有外键约束,但删除所有者(USER)表确实也可以通过休眠句柄正确删除子(USERDETAIL)表。

    我也不需要担心更新没有子字段的所有者表。 mappedBy 端实际上没有定义为 Khue Vu 所说的物理映射。 Hibernate 足够聪明,不会删除关系。

    【讨论】:

      猜你喜欢
      • 2017-05-18
      • 2012-01-23
      • 2015-03-25
      • 1970-01-01
      • 2021-01-08
      • 2019-02-18
      • 2014-09-13
      • 2019-12-30
      相关资源
      最近更新 更多