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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нужен совет по архитектуре, Persistent objects 
V
    Опции темы
User1302
Дата 1.11.2011, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте, нужен совет по архитектуре.

Попробую максимально упростить.
Программа использует средства и компоненты: Swing, Hibernate и базу данных.

Есть интересующий нас бизнес-обьект. Он представлен сохраняемым (Persistent) классом, пусть PObject. В программе есть 2 два независимых друг от друга компонента Jcomponent, кот. определенным образом позволяют работать с одними и теми же экземплярами PObject.

Для простоты допустим, что эти два компонента - содержат в себе списки JList, заключающие в себе экземпляры PObject.
Каждый из компонентов должен уметь обновлять свой список из базы данных самостоятельно, так как по идее, эти компоненты ничего друг о друге не знают.
Для этого берется Hibernate сессия Session, достается список List из базы, обновляется список JList компонента.

Возникает необходимость перетаскивания объектов PObject из первого компонента во второй, и наоборот. При перетаскивании появление экземпляра PObject в Target-компоненте должно происходить в случае его отсутствия в Target-компоненте. Если использовать отдельные сессии Hibernate для каждого компонента возникает ситуация когда один и тот же бизнес-обьект, кот. сохранен в базе данных, будет представлен разными экземплярами PObject.
Получается, при перетаскивании мне нужно проверять наличие в Target-компоненте именно бизнес-обьекта (например, сравнивать Id), а не просто приравнивать java-обьекты оператором "==".

Писать вот такие костыли для проверки Id-шников объектов неправильно.

Вижу два выхода:
1) Доставать обьекты из одной сессии Hibernate. В этом случае нужно что ли сделать одну сессию на все приложение и ею пользоваться.
2) Сделать кеш второго уровня, например EhCache прикрутить, чтоб из разных сессий дергать одни и те же объекты.

Не знаю, по какому пути пойти.
При переносе ПО на сервер, видимо, нужно будет использовать transaction-manager для определения контекста пользователя и предоставления ему Session.

Сейчас hibernate настроен на получение Thread-зависимой сессии, то есть, для каждого потока выделяется сессия.
Ничего подобного еще не писал, так что, в принципе, вопрос этот - вопрос новичка.

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

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

В каком направлении двигаться? 

Спасибо!
PM MAIL   Вверх
LSD
Дата 1.11.2011, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


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

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



Цитата(User1302 @  1.11.2011,  13:11 Найти цитируемый пост)
Получается, при перетаскивании мне нужно проверять наличие в Target-компоненте именно бизнес-обьекта (например, сравнивать Id), а не просто приравнивать java-обьекты оператором "==".

Ну воообще-то в Java по == принято сравнивать только примитивные типа и enum-ы. Все остальные объекты принято сравнивать через equals(), в котором уже надо реализовать правильную логику сравнения. Есть специальные случаи когда объекты сравниваются через ==, но это исключение.


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


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


Новичок



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

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



Про "==" знаю - для ссылочных типов будет проверять, указывают ли ссылки на одну область памяти.
В equals() нужно будет реализовывать сравнение Id объектов.

Цитата

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


Меня как раз интересовало мнение общественности по поводу таких телодвижений, как "мержить".
Как раз насчет этого у меня были сомнения, нужно ли такой огород городить. Если такое кто-то делает, возможно, стоит подумать над этим. Спасибо!

Теперь по поводу моего проекта..
Сделать, как в варианте 1), то есть одну сессию на все приложение - не очень удобно в моем случае. Поясню, почему.
Представим, что в копмоненте1 (помните, я говорил о двух компонентах в начале поста?..) из объектов PObject строится некая сложная структура. В этой же базе хранятся всякие там "restrictions", кот. позволяют принимать решение, грузить следующий обьект из базы, или нет. То есть загрузка данных из базы в этом случае - некоторый длительный итерационный процесс.
В свою очередь, компонент под номером 2 простым бесхитростным образом вытягивает список объектов и это у него получается довольно-таки быстро. Мне не хочется ждать, пока компонент1 построит свою структуру и отпустит сессию.
Очевидно, параллельно к базе могут обращаться два компонента и это нужно делать в разных потоках.
Выходит, что на каждый поток нужна своя сессия, ведь объект Session не является потокобезопасным.

Я никогда не работал с cache, поэтому насчет следующего могу ошибаться:
В идеале я хочу, чтоб разные сессии возвращали мне один и тот же обьект PObject, если он уже где-то используется (где-то есть на него ссылки).
Возможно, с этим мне поможет кеш второго уровня? Или я ошибаюсь?

Даже если не ошибаюсь, вырисовывается другой вопрос:
Стоит ли завязывать всю логику приложения на "какой-то там кеш", который вообще прикручивается через конфигурационные файлы и выступает в роли просто "примочки", кот. позволяет ускорить работу приложения и которого может и не быть, или который может быть заменен другим поставщиком кеша, который, к тому же, может работать не так, как нужно.??
Поправьте меня, если я ошибаюсь.

Интересно, как люди это делают, боюсь наламать дров.

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


Leprechaun Software Developer
****


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

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



Цитата(User1302 @  1.11.2011,  18:22 Найти цитируемый пост)
Меня как раз интересовало мнение общественности по поводу таких телодвижений, как "мержить".

У тебя есть два места в памяти где хранятся сущности, причем они могут независимо модифицироваться, и плюс ко всему этому есть база. Которая вроде того как source of truth. Естественно тут придется повертеться, чтобы это все заработало. Можно упростить схему, но для этого надо где-то отказаться от изменений. Или не держать изменений в памяти, сразу писать их в базу.


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


Новичок



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

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



Цитата(LSD @  2.11.2011,  11:42 Найти цитируемый пост)
У тебя есть два места в памяти где хранятся сущности, причем они могут независимо модифицироваться, и плюс ко всему этому есть база. Которая вроде того как source of truth. Естественно тут придется повертеться, чтобы это все заработало. Можно упростить схему, но для этого надо где-то отказаться от изменений. Или не держать изменений в памяти, сразу писать их в базу.

Когда придумывал приложение, представлял себе, что места, где хранятся сущности (я так понимаю, Вы про мои "компоненты" говорите), могут добавляться во время постепенного расширения приложения, и в каждом таком месте (компоненте) возможно изменение объекта. При изменении объект бросается во "flush-очередь", содержимое которой сбрасывается в БД при нажатии кнопочки с пиктограммой дискетки "сохранить".

Тема, в общем, остается открытой, а именно, вопрос о том, стоит ли заморачиваться с тем, чтоб для всего приложения мог существовать только один экземпляр обьекта PObject, то есть одна запись в таблице = одному Java-объекту, с которым работают множество потоков?
Или же смотреть в сторону "мержить"?

LSD, спасибо!
PM MAIL   Вверх
Skipy
Дата 2.11.2011, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Вопрос на засыпку. А зачем использовать разные сессии для компонент? Сессия в них должна поставляться извне, через dependency injection. Вот и поставляйте один экземпляр, тогда перетаскиваемые объекты будут в одной сессии. А компоненты по-прежнему ничего не будут знать друг о друге.


--------------------
С уважением,
Евгений aka Skipy
www.skipy.ru
PM MAIL WWW ICQ   Вверх
User1302
Дата 2.11.2011, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Skipy @  2.11.2011,  16:57 Найти цитируемый пост)
Вопрос на засыпку. А зачем использовать разные сессии для компонент?

У компонент разное время обновлений из БД. Например, у первого - от 10сек до 20сек. У второго - миллисекунды.
Нужно пока строится структура в первом компоненте, беспрепятственно строить/обновлять второй компонент.
PM MAIL   Вверх
User1302
Дата 3.11.2011, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Решение, конечно, напрашивается само:
Использовать разные сессии, разные java-объекты для одного бизнес-объекта, сравнивать эти объекты по полю Id, и так работать.

Неужто никто не сталкивался с подобным?
Может быть, я не совсем понятно объяснил?

Хотелось услышать побольше мнений..

PM MAIL   Вверх
lazycat
Дата 3.11.2011, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



IMHO для того, чтобы принять конкретное решение, надо еще очень много чего уточнить, но "навскидку" я бы предпочел подход, при котором каждый PObject хранился бы в памяти только в одном экземпляре. В противном случае, мне кажется, на каждом этапе разработки будут возникать все новые и новые проблемы с синхронизацией.

PM MAIL   Вверх
User1302
Дата 4.11.2011, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Что если сделать так:
1) Написать кэш для persistent объектов на фантомных ссылках.
2) Дописать Hibernate таким образом, чтобы сессия искала объект по Id в кэше.
    - Если находит объект в кэше - изменяет его в соответствии с данными полей, кот. вытянут из БД, возвращает объект из кеша.
    - Если не находит объект в кэше - создает новый по стандартной схеме Hibernate, возвращает новый обьект.
Тогда любая сессия будет возвращать один и тот же экземпляр, если на него уже есть где-либо в приложении ссылки.

О трудностях этой задачи еще не думал, нужно поковырять Хибер.

Есть мысли?
PM MAIL   Вверх
LSD
Дата 7.11.2011, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


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

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



Цитата(Skipy @  2.11.2011,  17:57 Найти цитируемый пост)
Сессия в них должна поставляться извне, через dependency injection. Вот и поставляйте один экземпляр, тогда перетаскиваемые объекты будут в одной сессии.

1. У хибера сессия не синхронизирована.
2. Это противоречит рекомендациям хибернейта:
Цитата
A Session is an inexpensive, non-threadsafe object that should be used once and then discarded for: a single request, a conversation or a single unit of work.



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


Новичок



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

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



Цитата(LSD @  7.11.2011,  15:02 Найти цитируемый пост)
1. У хибера сессия не синхронизирована.
2. Это противоречит рекомендациям хибернейта:


Что касается кэша 2-го уровня: насколько понял по документации, кэш не хранит "инстансы" объектов, а хранит объекты в разобранном виде.
Это значит, что в контексте сессии всегда создается новый экземпляр объекта. Так что, не выйдет воспользоваться кэшем 2-го уровня для получения одного и того же экземпляра PObject через разные сессии (см. мое первое сообщение, там описано зачем).

Дальше, насчет моего вот этого:
Цитата

2) Дописать Hibernate таким образом, чтобы сессия искала объект по Id в кэше.
    - Если находит объект в кэше - изменяет его в соответствии с данными полей, кот. вытянут из БД, возвращает объект из кеша.
    - Если не находит объект в кэше - создает новый по стандартной схеме Hibernate, возвращает новый объект.


Если даже такое сделать, - это будет один большой костыль.
При расширении системы в дальнейшем всегда нужно будет иметь ввиду, что мы работаем через эту "изуродованную" сессию, привязывать к ней весь код.
Вывод: нужно выработать подход, как сделать так, чтоб разные инстансы одного бизнес объекта мирно сосуществовали в одном приложении, подумать над тем, чтоб меньше использовать памяти.

Думаю, тему можно закрыть.

Всем спасибо за помощь!
PM MAIL   Вверх
LSD
Дата 11.11.2011, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


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

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



Цитата(User1302 @  10.11.2011,  12:41 Найти цитируемый пост)
Что касается кэша 2-го уровня: насколько понял по документации, кэш не хранит "инстансы" объектов, а хранит объекты в разобранном виде.

Кстати, да 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   Вверх
User1302
Дата 18.11.2011, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Может быть, вот эта ссылка будет кому интересна:
https://forum.hibernate.org/viewtopic.php?f=1&t=965080

Что касается приложения - подход пока не определен. Колеблюсь то в одну, то в другую сторону каждый день буквально.
PM MAIL   Вверх
User1302
Дата 18.11.2011, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Такая-себе "квинтэссенция":
http://blog.schauderhaft.de/2008/09/28/hib...t-applications/
+1шаг к решению проблемы smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Design, Quality, Testing | Следующая тема »


 




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


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

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