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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Маппинг generic коллекций (Hibernate), Не могу замаппить generic коллекцию 
:(
    Опции темы
INlHELL
Дата 14.1.2010, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Всем доброго времени суток!
Столкнулся со следующей проблемой, в упрощённом виде выглядет так: есть класс First и есть класс Second никак не связанный с First.
Необходимо создать "универсалный контейнер" для хранения наборов этих объектов. Т.е. generic класс с коллекцией, который принимает объекты обоих типов,
помещает их в коллекцию и сохраняет в БД.

Ниже классы тестового приложения:
Код

@Entity
@Table(name = "first")
public class First {
  private String uuid = UUID.randomUUID().toString();
  private String name;
  
  public First() {
    super();
    this.name = "First " + this.uuid;
  }

  @Id
  @Column(name = "firstId", nullable = false)
  public String getUuid() {
    return uuid;
  }

  public void setUuid(String uuid) {
    this.uuid = uuid;
  }

  @Column(name = "firstName")
  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
  
  public void putInContainer(Container<First> container) {
    Collection<First> collection = new ArrayList<First>();
    collection.add(this);
    container.setCollectionOfElements(collection);
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    First other = (First) obj;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    if (uuid == null) {
      if (other.uuid != null)
        return false;
    } else if (!uuid.equals(other.uuid))
      return false;
    return true;
  }

  @Override
  public String toString() {
    return "First [name=" + name + ", uuid=" + uuid + "]";
  }
  
}


Код

@Entity
@Table(name = "second")
public class Second {
  private String uuid = UUID.randomUUID().toString();
  private String name;
  private Color color;
  
  public Second() {
    super();
    this.name = "First " + this.uuid;
    this.color = Color.YELLOW;
  }
  
  @Id
  @Column(name = "secondId", nullable = false)
  public String getUuid() {
    return uuid;
  }
  public void setUuid(String uuid) {
    this.uuid = uuid;
  }
  
  @Column(name = "secondName")
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  
  @Column(name = "secondColor")
  public Color getColor() {
    return color;
  }
  public void setColor(Color color) {
    this.color = color;
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((color == null) ? 0 : color.hashCode());
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Second other = (Second) obj;
    if (color == null) {
      if (other.color != null)
        return false;
    } else if (!color.equals(other.color))
      return false;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    if (uuid == null) {
      if (other.uuid != null)
        return false;
    } else if (!uuid.equals(other.uuid))
      return false;
    return true;
  }
  @Override
  public String toString() {
    return "Second [color=" + color + ", name=" + name + ", uuid=" + uuid + "]";
  }
  
}


Самое интересное, контейнер:
Код

@Entity
@Table(name = "container")
public class Container<E> {

  private String uuid = UUID.randomUUID().toString();

  private Collection<E> collectionOfElements = new ArrayList<E>();

  public Container() {
    super();
  }
  
  @Id
  @Column(name = "containerId", nullable = false)
  public String getUuid() {
    return uuid;
  }

  public void setUuid(String uuid) {
    this.uuid = uuid;
  }
  
  
  @CollectionOfElements
  @OneToMany(targetEntity = First.class)
  public Collection<E> getCollectionOfElements() {
    return collectionOfElements;
  }

  public void setCollectionOfElements(Collection<E> collectionOfElements) {
    this.collectionOfElements = collectionOfElements;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime
        * result
        + ((collectionOfElements == null) ? 0 : collectionOfElements.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Container other = (Container) obj;
    if (collectionOfElements == null) {
      if (other.collectionOfElements != null)
        return false;
    } else if (!collectionOfElements.equals(other.collectionOfElements))
      return false;
    return true;
  }

  @Override
  public String toString() {
    return "Container [collectionOfElements=" + collectionOfElements + "]";
  }
  
}


Как можно обойти следующие анотации:  
 @CollectionOfElements
 @OneToMany(targetEntity = First.class)


В таком виде пример зарускается и данные вносятся в таблицы, но коллекция только для класса First и при попытке добавления экземпляра класса Second,
появляются эксепшены.

Активное "гугление" не помогло, есть мысль использовать супер класс и в качестве targetEntity указывать его, но для этого необзодима маппить и его и данное решение мне кажется несовсем верным.

Буду очень признателен за любую помощь!
PM MAIL   Вверх
afon
Дата 14.1.2010, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 85
Регистрация: 5.4.2008
Где: Украина, Киев

Репутация: нет
Всего: 1



Накатал большую телегу по мапингу с наследованием и связями, но передумал. 
1) На сколько сильно НИКАК НЕ СВЯЗАНЫ First и Second?
2) Сохраняется ли объект Container в базу?
3) имеет ли Container какую-то связь с First и Second?

Если 1) Сильно 2) нет, 3) нет - то храни их как хочешь, при любых раскладах будет щастье, выдергиваешь нужный List<First> или List<Second> запросом и суешь в свой Контейнер. 

Если 1) Есть общие поля 2) да 3) да - то выложу свою телегу smile

Это сообщение отредактировал(а) afon - 14.1.2010, 17:50
PM MAIL WWW   Вверх
LSD
Дата 14.1.2010, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


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

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



А как ты это у тебя в базе представлено? У тебя одна колонка содержит айдишники из двух разных таблиц?


--------------------
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   Вверх
INlHELL
Дата 14.1.2010, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

1) На сколько сильно НИКАК НЕ СВЯЗАНЫ First и Second?

Собственно вообще никак не связаны, т.е. это две независимые сущности.
Цитата

2) Сохраняется ли объект Container в базу?

Сохраняется, ниже приведу код  с тестовым приложением для этих классов.
Цитата

3) имеет ли Container какую-то связь с First и Second?

Не имеет и имеет не должен, в идеале (в конченом приложении) существует множество объектов не связанных иерархией наследования и другими связями (имею ввиду экземпляр одного объекта не содержит ссылок на экземпляр другого). И есть объект (Container) в который можно передать набор (в примере Collection) этих объектов. Главное, что Container должен принимать коллекцию любого типа (Firtst и Second в данном примере) и ничего "не знает" о них.

Код использующий эти классы (не догадался, надо было сразу выложить):
Код

public class TestPlatform {

  public static void main(String[] args) {
    AnnotationConfiguration myConfiguration;

    myConfiguration = new AnnotationConfiguration();
    myConfiguration.setProperty("hibernate.connection.url",
        "jdbc:mysql://localhost:3306/generic_collection");
    myConfiguration.setProperty("hibernate.connection.username", "version");
    myConfiguration.setProperty("hibernate.connection.password", "");
    myConfiguration.setProperty("hibernate.connection.writedelay", "0");
    myConfiguration.setProperty("hibernate.connection.driver_class",
        "com.mysql.jdbc.Driver");
    myConfiguration.setProperty("hibernate.connection.autocommit", "false");
    myConfiguration.setProperty("hibernate.dialect",
        "org.hibernate.dialect.MySQLDialect");
    myConfiguration.setProperty("hibernate.show_sql", "true");
    myConfiguration.setProperty("hibernate.hbm2ddl.auto", "create");
    myConfiguration.setProperty("hibernate.transaction.factory_class",
        "org.hibernate.transaction.JDBCTransactionFactory");
    myConfiguration.setProperty("hibernate.cache.provider_class",
        "org.hibernate.cache.HashtableCacheProvider");
    myConfiguration.setProperty("hibernate.current_session_context_class",
        "thread");
    myConfiguration.setProperty("hibernate.connection.charSet", "utf-8");
    
    myConfiguration.addAnnotatedClass(First.class);
    myConfiguration.addAnnotatedClass(Second.class);
    myConfiguration.addAnnotatedClass(Container.class);
    
    First f1 = new First();
    First f2 = new First();
    Second s1 = new Second();
    Second s2 = new Second();
    Second s3 = new Second();
    
    Collection<First> setFirstCollection = new ArrayList<First>();
    setFirstCollection.add(f1);
    setFirstCollection.add(f2);
    Collection<Second> setSecondCollection = new ArrayList<Second>();
    setSecondCollection.add(s1);
    setSecondCollection.add(s2);
    setSecondCollection.add(s3);

    
    Container<First> containerForFirst = new Container<First>();
    containerForFirst.setCollectionOfElements(setFirstCollection);
    
    Container<Second> containerForSecond = new Container<Second>();
    containerForSecond.setCollectionOfElements(setSecondCollection);
    
    SessionFactory sessionFactory1;

    sessionFactory1 = myConfiguration.buildSessionFactory();

    Session session1 = null;

    session1 = sessionFactory1.openSession();
    session1.beginTransaction();
    session1.save(f1);
    session1.save(f2);
    session1.save(s1);
    session1.save(s2);    
    session1.save(s3);
    session1.save(setSecondCollection);
    session1.save(setFirstCollection);
    session1.getTransaction().commit();

    session1.flush();
    session1.close();


Прошу прощения, что сразу не уточнил и за неказистость кода тоже, это исключительно тестовое приложение.

Буду благодарен за любой совет или мысль, как это можно реализовать.
PM MAIL   Вверх
INlHELL
Дата 14.1.2010, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



В предыдущем блоке кода скопировал две строки не те:
Код

...
session1.save(setSecondCollection);
session1.save(setFirstCollection);
...


Правильно конечно так:

Код

...
session1.save(containerForSecond);
session1.save(containerForFirst);
...


Структура БД вот такая.

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


Leprechaun Software Developer
****


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

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



Цитата(INlHELL @  14.1.2010,  18:43 Найти цитируемый пост)
Структура БД вот такая.

Прикрепи картинку к посту. У меня этот сайт заблокирован.


--------------------
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   Вверх
afon
Дата 14.1.2010, 19:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 85
Регистрация: 5.4.2008
Где: Украина, Киев

Репутация: нет
Всего: 1



В общем, похоже, что решение с collectionOfElements очень даже удачное для коллекций любых никак не связанных объектов. 
Меня только смущает, что 
Цитата

Собственно вообще никак не связаны, т.е. это две независимые сущности.

и в тоже время оба First и Second имеют одинаковые поля uuis и name. Но это наверное для простоты и просто совпадение. 

В любом случае, твой варинат работает, но возможны и другие. 
Например, можно отэкстендить каждый элемент от какого-нибудь пустого интерфейса, допустим, interface MyStorableCollectionItem, в свой Container прописать Collection<? extends MyStorableCollectionItem> и всех делов. Когда будешь поднимать конкретный Container из базы, всегда можно будет взять instanceof объектов, которые будут в листе. Тут вроде просто. 

Другие варианты могут базироваться на inheritance strategy, но они дадут свои ограничения. Например, расшаренные строчные id у всех реализаторов MyStorableCollectionItem, или общий пул числовых id. 

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



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

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

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


 




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


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

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