Однонаправленное отношение «многие к одному» в DataNucleus

Для контекста на стороне клиента я использую шаблон MVP, поэтому представление со списком One знает только идентификатор, и когда мой новый Many будет получен на сервере, я хочу иметь возможность просто обновить внешний ключ One с помощью "setOneId" или пустой объект One с идентификатором, установленным на желаемое значение.

Итак, я пытаюсь создать однонаправленную связь «многие к одному» в 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, просто обновляю idOne с помощью хорошего идентификатора в моем объекте Many.

Я нашел этот сообщение в блоге, но это с 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;
}

Я попробовал, но получил точно эту ошибку.

Я не понимаю, как я с этим борюсь. Моя цель - иметь таблицу, в которой хранятся некоторые справочные данные (например, список стран как класс One) и список «рабочих элементов» (например, город как класс Many), которые я создаю/обновляю без создания/обновления справочные данные, только его внешний ключ в объекте Many.


person Malexandre    schedule 08.11.2012    source источник
comment
Используйте отношение @MoneyToMany.   -  person Roman C    schedule 08.11.2012
comment
Вы имеете в виду @ManyToMany? В документации говорится, что он двунаправленный, а также используется присоединиться к столу. В моем случае объекту One не нужно знать Many.   -  person Malexandre    schedule 08.11.2012
comment
Если вы возьмете написанный вами код и удалите @Join, то это будет работать в JPA. Генератор кода сгенерирует таблицу для Many, в которой есть столбец, являющийся внешним ключом для One. Я не узнаю аннотацию @Join, поэтому подозреваю, что проблема именно в этом.   -  person Tom Anderson    schedule 08.11.2012
comment
Если вам не нужна таблица соединений, то зачем ставить @Join? документы DN определяют, как поместить эти отношения и какие таблицы вы получите, будь то JDO или JPA.   -  person DataNucleus    schedule 08.11.2012
comment
Я прочитал документы. В JPA нет примера для однонаправленного без таблицы соединения . В JDO говорится, что он работает точно так же, как One -To-One, но мы попытались, и это не сработало так, как ожидалось: он сохранил сторонний элемент One также при сохранении Many. Я отредактирую свой вопрос, чтобы добавить еще несколько тестов.   -  person Malexandre    schedule 08.11.2012
comment
однонаправленный без таблицы соединения — это то же самое, что и oneToOne, поэтому просто назовите его так. Один и многие аспекты определяются типом поля, а не какой-либо произвольной пользовательской аннотацией. Никакая спецификация постоянства (JDO или JPA) не определяет, что допустимо совместное использование столбцов для нескольких полей/свойств; если вы хотите обновить FK, вы обновляете отношение   -  person DataNucleus    schedule 11.11.2012


Ответы (2)


Если это однонаправленная ассоциация, а Many является стороной-владельцем (согласно вашему второму примеру), вы движетесь в неправильном направлении. Не имеет особого смысла делегировать ответственность за обновление и вставку на стороне-владельце однонаправленного отношения (как это делается с параметрами insertable=false и updateable=false).

РЕДАКТИРОВАТЬ: обновленный ответ Итак, вы хотите, чтобы многие к одному, со столбцом внешнего ключа на стороне владельца. Попробуй это

@Entity
public class Many {
    @Id
    String id;

    @ManyToOne
    @JoinColumn(name = "foreignKeyColumn")
    One one;
}
person JustDanyul    schedule 08.11.2012
comment
Я пытался быть ясным, очевидно, я не был, очень плохо. Мне не нужна таблица соединений, я хочу иметь внешний ключ на моем объекте-владельце. И я не хочу обновлять принадлежащий объект, когда я обновляю принадлежащий ему, я хочу просто обновить внешний ключ. - person Malexandre; 08.11.2012
comment
вы постите собственно где, я просто не очень внимательно читал. Мои извинения, в любом случае, я обновил свой ответ :) - person JustDanyul; 08.11.2012
comment
Пробовали, если не ошибаюсь, проблема в том, что DataNucleus сохраняет One при сохранении Many. Мы попробовали в OpenJPA, и это сработало. Я все еще надеюсь найти решение с DataNucleus, возможно, это ошибка, и проблема должна быть открыта на их трекере ... - person Malexandre; 08.11.2012
comment
просмотрев эту страницу datanucleus.org/products/datanucleus/jdo/orm /cascading.html , кажется, что datanucleus по умолчанию выполняет каскадное обновление. Попробуйте явно отключить каскадирование обновлений. - person JustDanyul; 08.11.2012

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

Это обновляет FK между A и B. Не может быть проще

person DataNucleus    schedule 16.11.2012