Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Unowned relations in AppEngine and JPA 
:(
    Опции темы
Sun
Дата 13.9.2011, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Есть проблема следующего характера. Есть две сущности Order и Contact. Между ними связь ManyToOne. Но связь не жесткая. То-есть существующий контакт может быть добавлен к заказу в любой момент времени. 

Код

@Entity
public class Order {

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Contact contact;


Однако при попытке назначить один и тот-же контакт другому заказу идет ошибка, по поводу того что нельзя изменить парента.

Цитата

Detected attempt to establish Order(89) as the parent of Order(86)/Contact(87) but the entity identified by Order(86)/Contact(87) is already a child of Order(86).  A parent cannot be established or changed once an object has been persisted.


Нашел статью где описано использование алиасов

http://gae-java-persistence.blogspot.com/2...bout-joins.html

Код

@Entity
public class Order {

    @Column(name = "contact", insertable = false, updatable = false)
    private Contact contact;


При связывании первого заказа с первым контактом все хорошо. Но когда другой заказ привязываешь к тому же контакту - сохраняется без ошибок, но при вытаскивании объекта заказа поле контакта имеет значение null.

Кто сталкивался с подобной проблемой? Может есть какие-то соображения?

Это сообщение отредактировал(а) Sun - 14.9.2011, 17:41


--------------------
Account removed
PM MAIL   Вверх
Farmazon
Дата 13.9.2011, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Разработчик
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 7.7.2006

Репутация: 3
Всего: 5



Кэш чистил?


--------------------
Таково моё общее мнение.
PM MAIL WWW   Вверх
Sun
Дата 13.9.2011, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Да, по колесам стучал. Багажник открывал - закрывал - не помогало.


--------------------
Account removed
PM MAIL   Вверх
Farmazon
Дата 14.9.2011, 05:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Разработчик
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 7.7.2006

Репутация: 3
Всего: 5



Код


@Entity
public class Order {
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Contact contact;

...

@Entity
public class Order {
    @OneToMany(mappedBy="contact")
private List<Contact> contactList;


Добавлено через 1 минуту и 11 секунд
ну примерно так должна разметка выглядеть для двусторонней связи....


--------------------
Таково моё общее мнение.
PM MAIL WWW   Вверх
Sun
Дата 14.9.2011, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(Farmazon @  14.9.2011,  02:42 Найти цитируемый пост)
ну примерно так должна разметка выглядеть для двусторонней связи.... 

Мне не нужна двухсторонняя связь. Мне нужна возможность привязывать один и тотже контакт к неограниченному числу заказов, в любой момент времени. А потом иметь возможность вытянуть контакт из сохраненного заказа. Вот такое простое желание.

Это сообщение отредактировал(а) Sun - 14.9.2011, 17:29


--------------------
Account removed
PM MAIL   Вверх
LSD
Дата 14.9.2011, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 5
Всего: 538



Цитата(Sun @  14.9.2011,  18:28 Найти цитируемый пост)
Мне не нужна двухсторонняя связь. Мне нужна возможность привязывать один и тотже контакт к неограниченному числу заказов, в любой момент времени. А потом иметь возможность вытянуть контакт из сохраненного заказа.

Так второе не противоречит первому smile 

Покажи как у тебя сделан маппинг на обоих сторонах.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Farmazon
Дата 14.9.2011, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Разработчик
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 7.7.2006

Репутация: 3
Всего: 5



чёт я правда не внимателен... 


нужно больше кода.

Добавлено через 42 секунды
в базе-то сохраняется?...


--------------------
Таково моё общее мнение.
PM MAIL WWW   Вверх
Sun
Дата 14.9.2011, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(LSD @  14.9.2011,  15:13 Найти цитируемый пост)
Так второе не противоречит первому  

Покажи как у тебя сделан маппинг на обоих сторонах. 


Маппинг только на одной стороне - в заказе. Потому что контакт - универсальный объект и может линковаться не только к заказу но и к другим сущностям. Поэтому у контакта нет мапинга на заказ:

Код

@Entity
public class Order {
@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key orderId;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Contact contact;


...

@Entity
public class Contact {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key contactId;


а сохранение выглядит так:

Код

EntityManager em = EMFService.get().createEntityManager();
Order order = new Order();
...
Contact contact = new Contact();
...
order.setContact(contact);
em.getTransaction().begin();
em.persist(order);
em.getTransaction().commit();        


Первый заказ и первый контакт сохраняется и достается из базы прекрасно. При попытке сохранить второй заказ с тем же контактом идет ошибка:

Цитата

Detected attempt to establish Order(89) as the parent of Order(86)/Contact(87) but the entity identified by Order(86)/Contact(87) is already a child of Order(86).  A parent cannot be established or changed once an object has been persisted.



Это сообщение отредактировал(а) Sun - 15.9.2011, 09:13


--------------------
Account removed
PM MAIL   Вверх
Sun
Дата 14.9.2011, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Пришлось делать очень грязный хак. 

Код

@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key orderId;

    @Basic
    private Key contactKey;
    
    @Column(name = "contact", insertable = false, updatable = false)
    private Contact contact;

...
@Entity
public class Contact {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key contactId;



Код

        EntityManager em = EMFService.get().createEntityManager();        
        Order order = (Order)em.find(Order.class, orderId);
        RpcOrder result = null;
        if (order != null) {
            Query query = em.createQuery("SELECT FROM Contact c WHERE c.contactId = ?1");
            query.setParameter(1, order.getContactKey());
            Contact contact = null;
            try {
                contact = (Contact) query.getSingleResult();
                order.setContact(contact);
            } catch (NoResultException nr) {}
        


Но это работает! Ничего лучше придумать не вышло.

Это сообщение отредактировал(а) Sun - 15.9.2011, 09:27


--------------------
Account removed
PM MAIL   Вверх
LSD
Дата 16.9.2011, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 5
Всего: 538



Попробуй указать @JoinColumn.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sun
Дата 18.9.2011, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(LSD @ 16.9.2011,  14:44)
Попробуй указать @JoinColumn.

Не идет. Получаю туже ошибку:

Цитата

Detected attempt to establish Order(130) as the parent of Contact(105) but the entity identified by Contact(105) has already been persisted without a parent.  A parent cannot be established or changed once an object has been persisted.




--------------------
Account removed
PM MAIL   Вверх
LSD
Дата 19.9.2011, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 5
Всего: 538



Вот так у меня все заработало:
Код

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "tst_child")
public class Child {
    @Id
    @Column(name = "child_id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ChildSeq")
    @SequenceGenerator(name = "ChildSeq", sequenceName = "tst_child_seq", allocationSize = 1)
    private long id;

    @ManyToOne(
            targetEntity = Parent.class,
            fetch = FetchType.LAZY,
            cascade = CascadeType.REFRESH
    )
    @JoinColumn(name = "parent_id")
    private Parent parent;

    public Child() {
    }

    public long getId() {
        return id;
    }

    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Child)) return false;

        Child that = (Child) o;

        return this.id == that.id;
    }

    @Override
    public int hashCode() {
        return (int) (id ^ (id >>> 32));
    }

    @Override
    public String toString() {
        return "Child{" +
               "id=" + id +
               ", parent=" + parent +
               '}';
    }
}

Код

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "tst_parent")
public class Parent {
    @Id
    @Column(name = "parent_id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ParentSeq")
    @SequenceGenerator(name = "ParentSeq", sequenceName = "tst_parent_seq", allocationSize = 1)
    private long id;

    public Parent() {
    }

    public long getId() {
        return id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Parent)) return false;

        Parent that = (Parent) o;

        return this.id == that.id;
    }

    @Override
    public int hashCode() {
        return (int) (id ^ (id >>> 32));
    }

    @Override
    public String toString() {
        return "Parent{" +
               "id=" + id +
               '}';
    }
}

Код

CREATE TABLE tst_parent
(
   parent_id    BIGINT (20) NOT NULL
);

ALTER TABLE tst_parent ADD CONSTRAINT pk_tst_parent PRIMARY KEY (parent_id);

CREATE SEQUENCE tst_parent_seq
   START WITH 1
   INCREMENT BY 1;


CREATE TABLE tst_child
(
   child_id     BIGINT (20) NOT NULL,
   parent_id    BIGINT (20)
);

ALTER TABLE tst_child ADD CONSTRAINT pk_tst_child PRIMARY KEY (child_id);

CREATE SEQUENCE tst_child_seq
   START WITH 1
   INCREMENT BY 1;

База H2, Persistence Provider - Hibernate.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sun
Дата 19.9.2011, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(LSD @  19.9.2011,  13:53 Найти цитируемый пост)
База H2, Persistence Provider - Hibernate. 

К сожалению я не могу использовать Hibernate с AppEngine. Datastorage используемый в AppEngine имеет ряд ограничений, в силу того что используется не реляционная СУБД, а так называемый Bigtable.

У меня изначально реализация была на Hibernate с использованием MySQL. Там никаких проблем не было со связями. Я спокойно джойнил любые объекты, не особо задумываясь. Но тут такие фокусы не проходят. Всё равно спасибо!


--------------------
Account removed
PM MAIL   Вверх
Farmazon
Дата 20.9.2011, 06:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Разработчик
**


Профиль
Группа: Участник
Сообщений: 265
Регистрация: 7.7.2006

Репутация: 3
Всего: 5



Вот с этого и надо было начинать!11


--------------------
Таково моё общее мнение.
PM MAIL WWW   Вверх
Sun
Дата 20.9.2011, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(Farmazon @  20.9.2011,  03:52 Найти цитируемый пост)
Вот с этого и надо было начинать!11 

У меня в заголовке темы написано что я использую JPA с AppEngine. Когда создавал тему не подозревал о наличии подобных ограничений. Надеялся что кто-то сталкивался с подобной проблемой. Но похоже что нет. Может спрошу у разработчиков - вдруг что подскажут получше, чем я сделал.


--------------------
Account removed
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0618 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.