在我的 Play 应用程序中使用 Ebean/JPA,如何删除 OneToOne 关系中的对象?

Posted

技术标签:

【中文标题】在我的 Play 应用程序中使用 Ebean/JPA,如何删除 OneToOne 关系中的对象?【英文标题】:Using Ebean/JPA in my Play application, how can I delete an object in a OneToOne relationship? 【发布时间】:2012-08-23 13:45:28 【问题描述】:

我有以下课程:

import play.db.ebean.Model;
import javax.persistence.*;

@Entity
public class A extends Model 
    @Id
    private int id;

    /* Other irrelevant properties */

    @OneToOne(cascade = CascadeType.ALL, optional = true)
    private B b;


import play.db.ebean.Model;
import javax.persistence.*;

@Entity
public class B extends Model 
    @Id
    private int id;

    /* Other irrelevant properties */

    @OneToOne(mappedBy = "b")
    private A a;

    @OneToOne(cascade = CascadeType.ALL, optional = false)
    private C c;


import play.db.ebean.Model;
import javax.persistence.*;

@Entity
public class C extends Model 
    @Id
    private int id;

    /* Other irrelevant properties */

    @OneToOne(mappedBy = "c")
    private B B;

在数据库中是这样的:

Table    a
Columns  id, ... (other irrelevant columns), b_id

Table    b
Columns  id, ...(other irrelevant columns), c_id

Table    c
Columns  id, ...(other irrelevant columns)

现在在一个控制器方法中(对于那些熟悉 Play 的人)我有一个 A 的对象,并且想从数据库中删除它的属性“b”。这也应该级联到 c,因此 c 也被删除。 这是我目前的做法:

B b = a.getB();
b.delete();

这会引发异常:

[PersistenceException: ERROR execution DML bindLog[] error[Cannot 删除或更新父行:外键约束失败 (databasename.a, 约束 fk_a_payme_4 外键 (b_id) 参考b (id))]]

这基本上归结为我试图删除 b,而 a 在 b_id 列中仍然持有对 b 的外键引用,所以我应该首先将该引用设置为 null。

在 Java 中,这转换为:

B b = a.getB();
a.setB(null);
a.update();
b.delete();

这确实将对象 a 中对 b 的引用设置为 null 并正确删除 b 对象,但 c 不会从数据库中删除。 (为什么?我虽然级联属性会处理这个) 我发现解决此问题的唯一方法是也显式删除 c,如下所示:

B b = a.getB();
C c = b.getC();

b.setC(null);
b.update();
c.delete();

a.setB(null);
a.update();
b.delete();

不过我对此不是很满意,因为删除数据库中的两行已经是 8 行代码了,如果这张图中有更多的关系会更多。

至于我的问题:

如何从 a 中删除 b,以便首先自动删除从 a 到 b 的引用,以及如何确保在删除 b 时也删除 c?

提前谢谢你!

编辑:迄今为止最好的想法:将 a-b 关系的所有权转移到 b。

【问题讨论】:

【参考方案1】:

尝试使用

class A

   ......

   @JoinColumn(nullable=true)
   private B b;

   .......

有关更多信息,请参阅此问题What is the difference between @ManyToOne(optional=false) vs. @Column(nullable=false)。

【讨论】:

这与@OneToOne(optional = true) 有何不同? 感谢您的链接,我又学到了一些新东西。我看不出这如何解决我的问题,当我查看数据库设计时,它说表 'a' 中的列 'b_id' 可以为空,所以这不应该改变任何东西,对吧? 所以级联规则在 Ebean 中根本不起作用?好吧,至少我可以开始寻找更好的解决方案。谢谢,我已经接受了。 级联规则确实有效,但它不在生成的 DDL 中。您必须手动编辑生成的 DDL。所有生成的 DDL 都在 /conf/evolutions/ 中。您可以使用 Hibernate 作为替代方案。【参考方案2】:

我在@johny 的回答中遇到了一些问题。试试这个。

@JoinColumn(name = "b_id", nullable = false)

【讨论】:

以上是关于在我的 Play 应用程序中使用 Ebean/JPA,如何删除 OneToOne 关系中的对象?的主要内容,如果未能解决你的问题,请参考以下文章

Google Play 服务在我的 Android 游戏中无法正常运行

Google Play Service 的 proguard 配置,在我的应用程序中还是在 lib 项目中?

在我的 Google Play 帐户中,应用登录私钥按钮已禁用

发布我的应用程序后,如何在我的 google play 控制台上更改应用程序内容描述?

我的 google play 控制台中有关 libpng 的安全警报

尝试在我的应用中集成 Google Play 游戏时出现 API 异常