0

For the context, client-side I use the MVP pattern, so the view with the One list knows only the ID, and when my new Many is received on the server, I want to be able to just update the One's foreign key, with a "setOneId" or an empty One object with an ID set to the wanted value.

So I try to create a many-to-one unidirectional in DataNucleus, and I'm struggling a bit. I'm ok to use JDO or JPA, I don't really care. In JPA, I tried this :

@Entity
public class Many {
    @Id
    String id;

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

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

It's almost what I want. The one-to-many is created but with a join table. I want to have a direct relation. And when I insert/update a Many, I don't want to insert/update the related One, just update the idOne with the good id in my Many object.

I found this blogpost, but it's with Hibernate, and I think it still use a join table :

@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;
}

I tried it, but I got exactly this error.

I don't understand how I am struggling with that. My goal is to have a table that keep some reference data (like a list of country as the class One), and a list of "working item" (like a town as the class Many) that I create/update without create/update the reference data, just its foreign key in the Many object.

Malexandre
  • 215
  • 2
  • 8
  • Use `@MoneyToMany` relationship. – Roman C Nov 08 '12 at 11:09
  • You mean @ManyToMany ? [The documentation](http://www.datanucleus.org/products/datanucleus/jpa/orm/many_to_many.html) say that it's bidirectional, and it also use a join table. The `One` object doesn't need to know the `Many` in my case. – Malexandre Nov 08 '12 at 11:15
  • If you take the code you've written, and remove the `@Join`, then that would work in JPA. A code generator would generate a table for `Many` which had a column which was a foreign key to `One`. I don't recognise the `@Join` annotation, so i suspect that this is what is causing the problem. – Tom Anderson Nov 08 '12 at 13:57
  • If you don´t want a join table then why put @Join? the DN docs define how to put these relations and what tables you get, whether JDO or JPA – DataNucleus Nov 08 '12 at 14:55
  • I've read the docs. In [JPA](http://www.datanucleus.org/products/datanucleus/jpa/orm/many_to_one.html), there is no example for unidirectional without join table. In [JDO](http://www.datanucleus.org/products/datanucleus/jdo/orm/many_to_one.html), it is said to do exactly like a One-To-One, but we tried, and it didn't worked as expected : it saved the foreign item `One` also when saving the `Many`. I'll edit my question to add some more test. – Malexandre Nov 08 '12 at 15:20
  • "unidirectional without join table" is the same as oneToOne, so just label it as that. The "one" and "many" aspect is defined by the type of the field not by some arbitrary user annotation. No persistence spec (JDO or JPA) defines that it is acceptable to share columns for multiple fields/properties; if you want to update an FK you update the relation – DataNucleus Nov 11 '12 at 09:35

2 Answers2

1

If its a unidirectional association, and Many is the owning side (as per your second example), you are heading in the wrong direction. It doesn't make much sense to delegate the update and insert responsibility on the owning side of a unidirectional relationship (as done with the insertable=false and updateable=false).

EDIT: updated answer So what you want is a many-to-one, with a foreign key column on the owning side. Try this

@Entity
public class Many {
    @Id
    String id;

    @ManyToOne
    @JoinColumn(name = "foreignKeyColumn")
    One one;
}
JustDanyul
  • 13,813
  • 7
  • 53
  • 71
  • I tried to be clear, obviously I wasn't, too bad. I don't want a join table, I want to have a foreign key on my owning object. And I don't want to update the owned object when I update the owning one, I want to just update the foreign key. – Malexandre Nov 08 '12 at 11:35
  • you post actually where, I just didn't read it very well. My apologies, anyways, I updated my answer :) – JustDanyul Nov 08 '12 at 13:50
  • We tried that if I'm not mistaken, the problem is that with DataNucleus, it saves the `One` when saving the `Many`. We tried in OpenJPA, and it worked though. I'm still hoping to find a solution with DataNucleus, maybe it's a bug and an issue must be open on their tracker... – Malexandre Nov 08 '12 at 15:23
  • from looking at this page http://www.datanucleus.org/products/datanucleus/jdo/orm/cascading.html , it seems that datanucleus cascades updates by default. Try explicitly turning off cascading on updates. – JustDanyul Nov 08 '12 at 15:50
1
@Entity
public class A {
    @Id
    String id;

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

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

and then if you persisted initial objects as

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();

This updates the FK between A and B. Can't get simpler

DataNucleus
  • 15,497
  • 3
  • 32
  • 37