【问题标题】:Many-to-one unidirectional relation in DataNucleusDataNucleus 中的多对一单向关系
【发布时间】:2012-11-08 11:01:12
【问题描述】:

对于上下文,我在客户端使用 MVP 模式,因此带有 One 列表的视图只知道 ID,当我的新 Many 在服务器上收到时,我希望能够使用“setOneId”或空的One 对象更新One 的外键,并将ID 设置为所需值。

所以我尝试在 DataNucleus 中创建一个多对一的单向,但我有点挣扎。我可以使用 JDO 或 JPA,我真的不在乎。在 JPA 中,我试过这个:

@Entity
public class Many {
    @Id
    String id;

    @ManyToOne
    @Join(name = "idOne")
    One one;
}

@Entity
public class One {
    @Id
    String id;
}

这几乎就是我想要的。创建了一对多但使用连接表。我想有一个直接的关系。当我插入/更新Many 时,我不想插入/更新相关的One,只需使用Many 对象中的好ID 更新idOne

我找到了这个blogpost,但它与 Hibernate 一起使用,我认为它仍然使用连接表:

@Entity
public class Many {
    @Id
    public String id;

    @Column(name="idOne")
    private String idOne;

    @ManyToOne
    @JoinColumn(name="idOne", nullable=false, insertable=false, updatable=false)
    private One one;
}

我试过了,但我得到的正是this error

我不明白我是如何挣扎的。我的目标是有一个表格来保存我创建/更新的一些参考数据(例如国家/地区列表One)和“工作项目”列表(例如城镇Many)无需创建/更新引用数据,只需其在 Many 对象中的外键。

【问题讨论】:

  • 使用@MoneyToMany 关系。
  • 你的意思是@ManyToMany? The documentation 说它是双向的,它也使用连接表。在我的例子中,One 对象不需要知道 Many
  • 如果您使用您编写的代码,并删除@Join,那么这将在 JPA 中工作。代码生成器将为Many 生成一个表,其中有一列是One 的外键。我不认识 @Join 注释,所以我怀疑这是导致问题的原因。
  • 如果您不想要一个连接表,那么为什么要使用@Join? DN 文档定义了如何放置这些关系以及你得到什么表,无论是 JDO 还是 JPA
  • 我已阅读文档。在JPA 中,没有单向无连接表的示例。在JDO 中,据说与一对一的操作完全一样,但我们尝试过,但并没有按预期工作:它保存了外部项目One,同时保存了Many。我将编辑我的问题以添加更多测试。

标签: java jpa jdo datanucleus many-to-one


【解决方案1】:

如果它是单向关联,并且 Many 是拥有方(根据您的第二个示例),那么您的方向是错误的。将更新和插入职责委派给单向关系的拥有方没有多大意义(就像 insertable=false 和 updateable=false 所做的那样)。

编辑:更新的答案 所以你想要的是一个多对一的,在拥有方有一个外键列。试试这个

@Entity
public class Many {
    @Id
    String id;

    @ManyToOne
    @JoinColumn(name = "foreignKeyColumn")
    One one;
}

【讨论】:

  • 我试图澄清,显然我没有,太糟糕了。我不想要一个连接表,我想在我拥有的对象上有一个外键。而且我不想在更新拥有的对象时更新拥有的对象,我只想更新外键。
  • 你在哪里发帖,我只是没看清楚。无论如何,我很抱歉,我更新了我的答案:)
  • 我们尝试过,如果我没记错的话,问题是使用 DataNucleus,它在保存 Many 时会保存 One。我们在 OpenJPA 中进行了尝试,但它确实有效。我仍然希望通过 DataNucleus 找到解决方案,也许这是一个错误,必须在他们的跟踪器上打开一个问题......
  • datanucleus.org/products/datanucleus/jdo/orm/cascading.html这个页面看,似乎datanucleus默认会级联更新。尝试明确关闭更新的级联。
【解决方案2】:
@Entity
public class A {
    @Id
    String id;

    @OneToOne(cascade=CascadeType.ALL)
    B b;
}

@Entity
public class B {
    @Id
    String id;
}

然后如果你将初始对象持久化为

tx.begin();
A a = new A("FirstA");
B b1 = new B("FirstB");
B b2 = new B("SecondB");
a.setB(b1);
em.persist(a);
em.persist(b2);
tx.commit();

... (some time later)
tx.begin();
A a = em.find(A.class, "FirstA");
B b2 = em.getReference(B.class, "SecondB");

// update the B in A to the second one
a.setB(b2);
tx.commit();

这会更新 A 和 B 之间的 FK。再简单不过了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多