|
Модераторы: LSD |
|
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 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-зависимой сессии, то есть, для каждого потока выделяется сессия. Ничего подобного еще не писал, так что, в принципе, вопрос этот - вопрос новичка. Хочется избрать правильный путь для как можно более легкого рефакторинга в дальнейшем. Исходить ли из того, что на каждого пользователя должна быть одна своя сессия? А поскольку приложение пока однопользовательское, то, выходит, для всего приложения будет одна сессия. Или положиться на кеш второго уровня и создавать сессии когда вздумается? В каком направлении двигаться? Спасибо! |
|||
|
||||
LSD |
|
|||
Leprechaun Software Developer Профиль Группа: Модератор Сообщений: 15708 Регистрация: 24.3.2004 Репутация: 1 Всего: 537 |
Ну воообще-то в 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. |
|||
|
||||
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Про "==" знаю - для ссылочных типов будет проверять, указывают ли ссылки на одну область памяти.
В equals() нужно будет реализовывать сравнение Id объектов.
Меня как раз интересовало мнение общественности по поводу таких телодвижений, как "мержить". Как раз насчет этого у меня были сомнения, нужно ли такой огород городить. Если такое кто-то делает, возможно, стоит подумать над этим. Спасибо! Теперь по поводу моего проекта.. Сделать, как в варианте 1), то есть одну сессию на все приложение - не очень удобно в моем случае. Поясню, почему. Представим, что в копмоненте1 (помните, я говорил о двух компонентах в начале поста?..) из объектов PObject строится некая сложная структура. В этой же базе хранятся всякие там "restrictions", кот. позволяют принимать решение, грузить следующий обьект из базы, или нет. То есть загрузка данных из базы в этом случае - некоторый длительный итерационный процесс. В свою очередь, компонент под номером 2 простым бесхитростным образом вытягивает список объектов и это у него получается довольно-таки быстро. Мне не хочется ждать, пока компонент1 построит свою структуру и отпустит сессию. Очевидно, параллельно к базе могут обращаться два компонента и это нужно делать в разных потоках. Выходит, что на каждый поток нужна своя сессия, ведь объект Session не является потокобезопасным. Я никогда не работал с cache, поэтому насчет следующего могу ошибаться: В идеале я хочу, чтоб разные сессии возвращали мне один и тот же обьект PObject, если он уже где-то используется (где-то есть на него ссылки). Возможно, с этим мне поможет кеш второго уровня? Или я ошибаюсь? Даже если не ошибаюсь, вырисовывается другой вопрос: Стоит ли завязывать всю логику приложения на "какой-то там кеш", который вообще прикручивается через конфигурационные файлы и выступает в роли просто "примочки", кот. позволяет ускорить работу приложения и которого может и не быть, или который может быть заменен другим поставщиком кеша, который, к тому же, может работать не так, как нужно.?? Поправьте меня, если я ошибаюсь. Интересно, как люди это делают, боюсь наламать дров. |
|||
|
||||
LSD |
|
|||
Leprechaun Software Developer Профиль Группа: Модератор Сообщений: 15708 Регистрация: 24.3.2004 Репутация: 1 Всего: 537 |
У тебя есть два места в памяти где хранятся сущности, причем они могут независимо модифицироваться, и плюс ко всему этому есть база. Которая вроде того как 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. |
|||
|
||||
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Когда придумывал приложение, представлял себе, что места, где хранятся сущности (я так понимаю, Вы про мои "компоненты" говорите), могут добавляться во время постепенного расширения приложения, и в каждом таком месте (компоненте) возможно изменение объекта. При изменении объект бросается во "flush-очередь", содержимое которой сбрасывается в БД при нажатии кнопочки с пиктограммой дискетки "сохранить". Тема, в общем, остается открытой, а именно, вопрос о том, стоит ли заморачиваться с тем, чтоб для всего приложения мог существовать только один экземпляр обьекта PObject, то есть одна запись в таблице = одному Java-объекту, с которым работают множество потоков? Или же смотреть в сторону "мержить"? LSD, спасибо! |
|||
|
||||
Skipy |
|
|||
Опытный Профиль Группа: Участник Сообщений: 487 Регистрация: 24.8.2006 Где: Москва, Россия Репутация: нет Всего: 16 |
Вопрос на засыпку. А зачем использовать разные сессии для компонент? Сессия в них должна поставляться извне, через dependency injection. Вот и поставляйте один экземпляр, тогда перетаскиваемые объекты будут в одной сессии. А компоненты по-прежнему ничего не будут знать друг о друге.
|
|||
|
||||
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
У компонент разное время обновлений из БД. Например, у первого - от 10сек до 20сек. У второго - миллисекунды. Нужно пока строится структура в первом компоненте, беспрепятственно строить/обновлять второй компонент. |
|||
|
||||
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Решение, конечно, напрашивается само:
Использовать разные сессии, разные java-объекты для одного бизнес-объекта, сравнивать эти объекты по полю Id, и так работать. Неужто никто не сталкивался с подобным? Может быть, я не совсем понятно объяснил? Хотелось услышать побольше мнений.. |
|||
|
||||
lazycat |
|
|||
Бывалый Профиль Группа: Участник Сообщений: 227 Регистрация: 15.7.2007 Репутация: нет Всего: 1 |
IMHO для того, чтобы принять конкретное решение, надо еще очень много чего уточнить, но "навскидку" я бы предпочел подход, при котором каждый PObject хранился бы в памяти только в одном экземпляре. В противном случае, мне кажется, на каждом этапе разработки будут возникать все новые и новые проблемы с синхронизацией.
|
|||
|
||||
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Что если сделать так:
1) Написать кэш для persistent объектов на фантомных ссылках. 2) Дописать Hibernate таким образом, чтобы сессия искала объект по Id в кэше. - Если находит объект в кэше - изменяет его в соответствии с данными полей, кот. вытянут из БД, возвращает объект из кеша. - Если не находит объект в кэше - создает новый по стандартной схеме Hibernate, возвращает новый обьект. Тогда любая сессия будет возвращать один и тот же экземпляр, если на него уже есть где-либо в приложении ссылки. О трудностях этой задачи еще не думал, нужно поковырять Хибер. Есть мысли? |
|||
|
||||
LSD |
|
||||
Leprechaun Software Developer Профиль Группа: Модератор Сообщений: 15708 Регистрация: 24.3.2004 Репутация: 1 Всего: 537 |
1. У хибера сессия не синхронизирована. 2. Это противоречит рекомендациям хибернейта:
-------------------- 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. |
||||
|
|||||
User1302 |
|
||||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Что касается кэша 2-го уровня: насколько понял по документации, кэш не хранит "инстансы" объектов, а хранит объекты в разобранном виде. Это значит, что в контексте сессии всегда создается новый экземпляр объекта. Так что, не выйдет воспользоваться кэшем 2-го уровня для получения одного и того же экземпляра PObject через разные сессии (см. мое первое сообщение, там описано зачем). Дальше, насчет моего вот этого:
Если даже такое сделать, - это будет один большой костыль. При расширении системы в дальнейшем всегда нужно будет иметь ввиду, что мы работаем через эту "изуродованную" сессию, привязывать к ней весь код. Вывод: нужно выработать подход, как сделать так, чтоб разные инстансы одного бизнес объекта мирно сосуществовали в одном приложении, подумать над тем, чтоб меньше использовать памяти. Думаю, тему можно закрыть. Всем спасибо за помощь! |
||||
|
|||||
LSD |
|
|||
Leprechaun Software Developer Профиль Группа: Модератор Сообщений: 15708 Регистрация: 24.3.2004 Репутация: 1 Всего: 537 |
Кстати, да -------------------- 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. |
|||
|
||||
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Может быть, вот эта ссылка будет кому интересна:
https://forum.hibernate.org/viewtopic.php?f=1&t=965080 Что касается приложения - подход пока не определен. Колеблюсь то в одну, то в другую сторону каждый день буквально. |
|||
|
||||
User1302 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Такая-себе "квинтэссенция":
http://blog.schauderhaft.de/2008/09/28/hib...t-applications/ +1шаг к решению проблемы |
|||
|
||||
COVD |
|
|||
Эксперт Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: нет Всего: 43 |
Мне кажется, все эти сложности от того, что на хибернет здесь возлагается слишком много.
Я бы начал с того, что определил модель приложения, в которой хранятся обьекты.
Обьекты в модель могут попасть из разных мест. Пользователь может создать обьект через ГУИ. Приложение может прочитать сериализованные обьекты из файла. Наконец, приложение может загрузить обьекты из базы данных. И вот в этом случае хибернет может быть использован как маппер, как парсер. Больше от него ничего не надо. Таким образом, уникальные обьекты хранятся в модели - синглтоне и доступны по ключу. Далее, если пользователь может открывать одновременно несколько view, которые отображают одни и те же данные, то это другая задача, которая никак не связана со способом сериализации обьектов. |
|||
|
||||
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Design, Quality, Testing | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |