【问题标题】:JPA cascade removeJPA 级联删除
【发布时间】:2012-03-23 17:45:45
【问题描述】:

我在删除另一个表引用的记录时遇到问题。

这是一个代码示例(最简单的场景):

@Entity
@Table(name = "user")
public class User
{
    @Id
    @GeneratedValue(generator="user_id_seq", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name="user_id_seq", sequenceName="user_id_seq")
    @Column(name = "id", nullable = false)
    private int id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
    private Set<UserLog> userLogSet;

    // Other attributes
    // Getters/setters
}

@Entity
@Table(name = "user_log")
public class UserLog
{
    @Id
    @GeneratedValue(generator="user_log_id_seq", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name="user_log_id_seq", sequenceName="user_log_id_seq")
    @Column(name = "id", nullable = false)
    private int id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    // Other attributes
    // Getters/setters
}

每当我尝试从“用户”表中删除记录时,我都会从 postgreSQL 收到以下错误:

错误:更新或删除表“用户”违反外键 表“user_log”上的约束“fk228a019fd2495d20”
详细信息:键 (id)=(5) 仍然从表“user_log”中引用。

我做错了什么?

谢谢!

更新:我尝试编写一个小例子,可以找到here。使用 Tomcat 启动应用程序后,会自动创建数据库模式(检查 /src/main/webapp/WEB-INF/jdbc.properties 中的连接详细信息)。当您访问http://localhost:8080 时,一些数据被插入到数据库中。如果我尝试删除 student 表中引用的任何 teacher(使用 phpPgAdmin),我会收到与上述类似的错误。

【问题讨论】:

    标签: spring postgresql jpa


    【解决方案1】:

    您的映射似乎有误。

    我猜用户可以有很多用户日志。

    @OneToMany 也应该在一个集合上,例如java.util.Set。 您放置的级联在 UserLog 中,如果您对 UserLog 的实例而不是 User 采取行动,就会发生这种情况。

    据我了解更改映射如下。

    @Entity
    @Table(name = "user")
    public class User
    {
        @Id
        @GeneratedValue(generator="user_id_seq", strategy = GenerationType.SEQUENCE)
        @SequenceGenerator(name="user_id_seq", sequenceName="user_id_seq")
        @Column(name = "id", nullable = false)
        private int id;
    
        @OneToMany(cascade = CascadeType.ALL,mappedBy="user")
        private Set<UserLog> userLogs;
    
        // Other attributes
        // Getters/setters
    }
    
    
    @Entity
    @Table(name = "user_log")
    public class UserLog
    {
        @Id
        @GeneratedValue(generator="user_log_id_seq", strategy = GenerationType.SEQUENCE)
        @SequenceGenerator(name="user_log_id_seq", sequenceName="user_log_id_seq")
        @Column(name = "id", nullable = false)
        private int id;
    
        @ManyToOne
        @JoinColumn(name = "user_id", nullable = false)
        private User user;
    
        // Other attributes
        // Getters/setters
    }
    

    我猜你想删除 User 及其所有 UserLog 只是删除 User 并离开 UserLogs 是没有意义的。

    希望这会有所帮助。

    更新:

    在实体类中注释的级联由 ORM 管理,而不是如果您 从外部尝试从 phpPgAdmin 等外部工具中删除它们。

    【讨论】:

    • 谢谢你,@gbagga——请参阅我在 madth3 问题中的评论,我只是在此处发布示例感到困惑。现在的重点是我不需要User 类中的Set,这是强制性的吗?有没有办法避免它?
    • @satoshi 它不是强制使用 Set,它基本上是用来避免重复对象最终与对象一起收集的。如果你有兴趣可以看看@hibernate docs
    • 谢谢你,@gbagga。不幸的是,即使使用您的解决方案,我也面临同样的问题。 JPA/Hibernate 应该在 PostgreSQL 中创建索引吗?还是所有的级联动作都由 ORM 管理?谢谢。
    • @satoshi 尝试将 orphanRemoval = true 添加到 @OneToMany 注释
    • 已经完成了,还是不行。我将构建这个完全简单的示例,以查看它是否有效。可能是在我的项目中不起作用,因为我使用 AspectJ 或其他东西......
    【解决方案2】:

    您的映射错误,OneToMany 应该在 User 中应用于 UserLog 的集合。见examples

    【讨论】:

    • 对不起,你是对的。在我正在处理的代码中,我使用的是ManyToOne,我只是对在这里发布一个示例感到困惑。 (编辑了原始问题)
    猜你喜欢
    • 2016-12-13
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多