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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Наследование в Hibernate, Как правильно прикастить к субклассу? 
V
    Опции темы
ming
  Дата 13.10.2009, 07:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Приветствую форумчан!


Имеется такая иерархия классов (модификаторы доступа и ненужные для общей картины элементы опущены):
Код

/** абстрактный класс, представляющий содержимое файлообменника */
abstract class Content {
    // общие поля типа Name, Description, Size, etc
}
class Film extends Content {
    int year; // год выпуска фильма
}
class Software extends Content {
    String version; // номер версии софтины
}

/** Категория, хранящая экземпляры подклассов класса Contеnt
Один подкласс - одна категория */
class Category {
    List<Content> items;
}


Наследование замаплено примерно так

Content.hbm.xml
Код

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="ru.balza.filex.logic.content">
    <class name="Content" abstract="true">
        <id column="CONTENT_ID" name="id">
            <generator class="native" />
        </id>        
        <discriminator column="DSK" type="string" length="30" not-null="true"/>
        
        <property name="name" type="string"/>
        <property name="description" type="string"/>
        <property name="size" type="int"/>
        <property name="URL" type="string"/>     
 
    <many-to-one name="category" class="Category" column="CATEGORY_ID" not-null="true" lazy="false"/>
 
    <bag name="tags" cascade="save-update" table="tags_and_content" lazy="false">
         <key column="CONTENT_ID"/>
         <many-to-many class="Tag" column="TAG_ID"/>
     </bag>
             
    <bag name="comments" cascade="save-update" lazy="false">
        <key column="CONTENT_ID"/>
        <one-to-many class="Comment"/>
    </bag>
    </class>
</hibernate-mapping>


Film.hbm.xml
Код

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="ru.balza.filex.logic.content">
    <subclass name="Film" extends="Content" discriminator-value="Film">
     <property name="originalName" column="original_name" type="string"/>
        <property name="director" type="string"/>
        <property name="year" type="int"/>
        <property name="country" type="string"/>           
    </subclass>
</hibernate-mapping>


Экземпляр Content (точнее экземпляр любого из его субклассов) вне Категории существовать не может и не должен. 
Это связывает меня по рукам и ногам тем, что когда я хочу вытащить из базы экзмепляр Contenta (т.е. его субклассов), 
мне нужно явно указывать конкретный субкласс, к которому полученный объект нужно будет прикастить.

Код

// где то в ContentDAO implementation
public Content getContentById(int contentId) throws SQLException {
    ...
    session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();    
    // 1.
    Content c = session.get(Content.class, contentId); // ошибка, Content - абстрактный класс
    // 2.
    Content c = session.get(Film.class,    contentId); // корректно
    // 3.
    Content c = session.get(Software.class, contentId); // так тоже корректно
    ...
    
    return c;
}

 
Получается что все время надо "таскать" за собой ссылку на этот нужный класс 
(Film или Software или любой другой подкласс Content).
В данный момент у меня это реализовано в виде метода в классе Category, 
возвращающего ссылку на класс объектов, которые хранит данная категория :

Код

class Category {
    List<Content> items;
    ...

    static final int UNDEFINED_TYPE = 0;
    static final int FILMS_TYPE    = 1;
    static final int SOFTWARE_TYPE    = 2;
    
    static final Map<Integer, Class> typesMap;
    static {
        typesMap = new HashMap<Integer, Class>();
        typesMap.put(UNDEFINED_TYPE,    null);
        typesMap.put(FILMS_TYPE,    Film.class);
        typesMap.put(SOFTWARE_TYPE,    Software.class);
    }
    ...

    /** тип категории, сигнализирует о том, объекты какого класса хранит категория */
    private int type; 
    ...

    public Class getContentClass() {
        return typesMap.get(type);
    }
}


инициализация категории:

Код

Category cat = new Category();
cat.setType(Category.FILMS_TYPE);
...


Применение:

Код

public class ContentDAOHibernateImpl implements ContentDAO {

...
    public Content getContentById(Category category, int contentId) throws SQLException {
        Session session = null;
        Content content = null;
        try {
            session = HibernateUtil.getSessionFactory().openSession();
            session.beginTransaction();    

            Class contentClass = category.getContentClass(); // ссылка на класс
            if (contentClass != null) {
                content = (Content) session.get(contentClass, contentId);
            }
        } catch(Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return content;
    }    
...
}



Хотелось бы узнать насколько такой способ хорош (или вообще допустим)?
Можно ли избавиться от повсеместного "таскания" Category?
Какова Best Practice, так сказать...

Это сообщение отредактировал(а) ming - 13.10.2009, 07:28
PM MAIL ICQ Jabber   Вверх
Quester82
Дата 13.10.2009, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(ming @ 13.10.2009,  07:15)
Хотелось бы узнать насколько такой способ хорош (или вообще допустим)?
Можно ли избавиться от повсеместного "таскания" Category?
Какова Best Practice, так сказать...

Почитай вот это...
http://black-zorro.com/mediawiki/Hibernate...ерархии_классов
Очень наглядно показано как сделать именно то что ты просишь, а также как просто избавиться от дискриминатора и прочей лабуды, хотя и не без издержек...

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


Шустрый
*


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

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



спасибо, полезная ссылочка!
переделал маппинг по методу "таблица для суперкласса, и по таблице для каждого подкласса"
PM MAIL ICQ Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0709 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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